大家好,应用系我是控制渔夫子。
今天给大家介绍一下如何利用go中的协程缓冲channel来控制协程的数量。如下示例:
package mainimport ( "fmt" "sync/atomic")func main() { sem := make(chan struct{ },数量 10) var count int32 for { //time.Sleep(5*time.Millisecond) go func() { sem <- struct{ }{ } atomic.AddInt32(&count, 1) defer func() { <-sem atomic.AddInt32(&count, -1) }() fmt.Printf("count is :%d\n", count) }() } }
在这个示例中,我们首先在for外层初始化了一个缓冲channel:sem,应用系该channel可以存放10个元素。控制在for循环中我们不停的协程启动协程。在协程中我们尝试往sem中发送元素,数量如果发送成功,应用系就运行后面的控制逻辑,如果发送不成功,协程即sem空间已经满了,就利用channel的堵塞特性,该协程在这里堵塞等待。最后等某个协程运行完毕后,从通道sem中输出一个元素,这样就腾出来一个空间,让堵塞的一个协程继续运行了。
这样,我们在for循环中虽然一直在不停的启用协程,但能够运行的协程数量不会超过10个。这样利用了通道的阻塞特定,不用加锁就能实现控制协程数量的目的。
在之前我们推荐过一个爬虫的开源项目:Geziyor。这个项目中就使用了这种方式来控制并发请求的数量。我们看下源代码:首先,在初始化的地方,先根据并发个数来初始化了一个缓冲通道,示例代码看源码第109行
图片
然后,在Start函数中,循环启动每一个采集的任务。源代码中的106行Start函数,如下:
图片
然后,在源代码的第220行,则启动任务协程,在任务协程中首先通过acquireSem函数往通道中发送一个消息,如果发送不成功就堵塞在这里,直到其他协程通过releaseSem释放通道中的一个空间出来。如下:
图片
好了,今天缓冲通道的其中应用场景就分享到这里。
责任编辑:武晓燕 来源: Go学堂 应用协程阻塞(责任编辑:百科)
比速科技(01372.HK)发布公告:拟发行4000万股认购股份
计算机十种常用编程语言Helloworld,最后一种你肯定没学过
从papi酱再到线上读书会,罗振宇会不会产品力跟不上营销力?
10月份全国服务业生产指数同比增长3.8% 总体保持恢复态势
南京银行(601009.SH)拟发行不超400亿元金融债券 一次或分次申报