之前写的协程有关的例子,为了保证所有协程都执行完毕后退出,我们都使用了 time.Sleep(time.Millisecond)
使主协程休眠,但在实际开发中我们并不能保证要休眠多久才能执行完毕,用多了主程序就阻塞了,用少了又会导致子协程的任务可能没法完成。下面我们介绍处理这种情况的方式。
使用信道
信道可以实现多个协程间的通信,于是乎我们可以定义一个信道,在任务执行完成后,往信道中写入 true
,然后在主协程中获取到 true
,就可以认为子协程已经执行完毕。
运行上面的程序,主协程就会等待创建的协程执行完毕后退出,运行后输出如下:
使用 WaitGroup
使用上面的信道方法,虽然可行,但在你程序中使用很多协程的话,你的代码就会看起来很复杂,这里就要介绍一种更好的方法,那就是使用 sync
包中提供的 WaitGroup 类型。WaitGroup
用于等待一批 Go 协程执行结束。程序控制会一直阻塞,直到这些协程全部执行完毕。当然 WaitGroup
也可以用于实现工作池。
WaitGroup
实例化后就能使用:
WaitGroup
有几个方法:
Add
:初始值为 0
,这里直接传入子协程的数量,你传入的值会往计数器上加。Done
:当某个子协程完成后,可调用此方法,会从计数器上减一,即子协程的数量减一,通常使用 defer
来调用。Wait
:阻塞当前协程,直到实例里的计数器归零。
运行上面的程序一种输出如下:
参考文献:
[1] Alan A. A. Donovan; Brian W. Kernighan, Go 程序设计语言, Translated by 李道兵, 高博, 庞向才, 金鑫鑫 and 林齐斌, 机械工业出版社, 2017.