第二十一篇:go协程练习:sync包入门、等待协程执行结束

:上节课代码

 

上节课代码逻辑是:通过协程来抓取,抓取完成以后使用主线程来执行写入,如果抓取和写入放到一个协程里就不需要管道来通信了,

怎么来判断我们协程全部执行完成了?我们接下来来了解sync这个包

 

:sync

 

sync中文意思是:同步。后面我们还会用到此包

 

其中sync包有个很有用的功能WaitGroup ,一共有3个方法

 

 Add(参数 int)done()wait()

 

内部创建一个计数器,使用

 

1Add 用来添加 goroutine 的个数

 

2Done 执行一次数量减 1, 好比Add(-1)

 

3Wait 用来阻塞主线程,直到所有协程执行完毕 (好比其他语言中的join())

 

我们在执行多个协程的时候,为了能判断出它们在执行完成我们在主线程里面执行wait用来阻塞主线程,直到所有协程执行完毕之后才能继续往下继续执行

 

测试代码:

 

 

:获取协程数

runtime,运行时系统交互操作,例如控制 goroutines 的函数。其中比较有用的几个方法

Gosched:让当前goroutine让出 cpu 以让其它goroutine运行,它不会挂起当前goroutine

NumCPU:返回当前系统的 CPU 核数

GOMAXPROCS:设置最大的可同时使用的 CPU 核数

Goexit:退出当前 goroutine(但是defer语句会照常执行)

NumGoroutine:返回正在执行和排队的任务总数

 

 利用sync包将 写入操作放在抓取的协程里执行

 

 

课外补充:defer

defer概述

defer语句是Go中一个非常有用的特性,可以将一个方法延迟到包裹该方法的方法返回时执行,在实际应用中,defer语句可以充当其他语言中try…catch…的角色,也可以用来处理关闭文件句柄等收尾操作。

defer触发时机

Go官方文档中对defer的执行时机做了阐述,分别是。

包裹defer的函数返回时

包裹defer的函数执行到末尾时

所在的goroutine发生panic

(1) :defer表达式中变量的值在defer表达式被定义时就已经明确

func a() {
    i := 0
    defer fmt.Println(i)
    i++
    return
}

所以,程序运行结束的时候,输出的结果是0而不是1

(2) defer表达式的调用顺序是按照先进后出的方式

(3) defer表达式中可以修改函数中的命名返回值

func c() (i int) {
    defer func() { i++ }()
    return 1
}

返回值变量名为i,在defer表达式中可以修改这个变量的值。所以,虽然在return的时候给返回值赋值为1,后来defer修改了这个值,让i自增了1,所以,函数的返回值是2而不是1

 

posted @ 2020-06-11 16:41  痞子胥  阅读(309)  评论(0)    收藏  举报