[Go] golang无缓冲通道实现工作池控制并发
展示如何使用无缓冲的通道创建一个goroutine池,控制并发频率
1.无缓冲通道保证了两个goroutine之间的数据交换
2.当所有的goroutine都忙的时候,能够及时通过通道告知调用者
3.无缓冲的通道不会有工作在队列里丢失或卡住
4.创建一个工作池,比如这时候会创建出2个goroutine,被一个无缓冲通道阻塞住,等待在那里,除非通道关闭,在当前的gorotine上会无限循环读取通道,不会退出
5.当有一堆的任务goroutine被发送过来的时候,会先传送给那一个通道,这时候不管有多少个,都会阻塞并等待上面那俩工作完,就起到了控制并发的目的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | package main import ( "log" "sync" "time" ) //定义一个Worker接口,有个必须实现的Task()方法 type Worker interface { Task() } //定义一个类型Pool,有两个成员 type Pool struct { //成员work,通道类型,传递的是Worker类型 work chan Worker //成员wg是计数信号量 wg sync.WaitGroup } //定义New方法,返回的是Pool实例 //传递的参数是goroutine池的数量 func New(size int) *Pool { //实例化Pool类型 pool := Pool{ work: make( chan Worker), } //增加计数信号量 pool.wg.Add(size) //使用循环创建多个goroutine for i := 0; i < size; i++ { //启动goroutine go func () { //从通道中获取值,这里如果没有会一直阻塞 //这里会无限循环遍历,除非通道关闭了,否则不会跳出当前这个goroutine for w := range pool.work { //调用Worker类型的Task()方法 w.Task() } }() pool.wg.Done() } return &pool } //给Pool类型定义Run方法 //参数是Worker类型 func (p *Pool) Run(w Worker) { //把Worker传进通道里 p.work <- w } //给Pool类型定义 Shutdown方法 func (p *Pool) Shutdown() { //关闭通道 close(p.work) //等待所有goroutine执行结束 p.wg.Wait() } //定义一个字符串数组 var names = []string{ "zhangsan" , "lisi" , "wangwu" , } //定义一个类型namePrinter type namePrinter struct { //成员name ,字符串类型 name string } //给类型实现Worker接口 func (np *namePrinter) Task() { //打印namePrinter类型的name成员 log.Printf(np.name) //睡眠一秒 time.Sleep(time.Second) } func main() { //创建2个goroutine的池,因为通道是空的,这个地方有两个goroutine会阻塞在那 pool := New(2) //定义计数信号量 var wg sync.WaitGroup //增加计数,100次乘以数组元素个数 wg.Add(100 * len(names)) //循环100次,这个地方会瞬间生成300个goroutine,大并发的去执行任务 for i := 0; i < 100; i++ { //循环数组 for _, name := range names { //实例化namePrinter类型 np := namePrinter{ name: name, } //启动一个goroutine go func () { //调用Pool类型的run方法 //传递的是Woker类型,因此要取地址 //这里会把该Worker类型,发送到通道里,如果通道不为空,就会阻塞住 //当300个goroutine,把name传递给run方法,会因为通道不为空被阻塞住 //通道何时才能为空呢,也就只有在工作池里的goroutine把通道读走 //因此会每次两个两个的打印,最多只会等待两个工作的完成 pool.Run(&np) wg.Done() }() } } //等待上面的100次遍历结束 wg.Wait() //停止工作池,关闭通道 pool.Shutdown() } |
十年开发经验程序员,离职全心创业中,历时三年开发出的产品《唯一客服系统》
一款基于Golang+Vue开发的在线客服系统,软件著作权编号:2021SR1462600。一套可私有化部署的网站在线客服系统,编译后的二进制文件可直接使用无需搭开发环境,下载zip解压即可,仅依赖MySQL数据库,是一个开箱即用的全渠道在线客服系统,致力于帮助广大开发者/公司快速部署整合私有化客服功能。
开源地址:唯一客服(开源学习版)
官网地址:唯一客服官网
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2016-02-23 [android] 点击事件的四种写法