前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >完整的golang 多协程+信道 任务处理示例

完整的golang 多协程+信道 任务处理示例

作者头像
李海彬
发布2018-03-26 17:12:25
1.6K0
发布2018-03-26 17:12:25
举报
文章被收录于专栏:Golang语言社区Golang语言社区
有几个地方需要注意:for i + 协程时如果协程使用可 i ,那么需要增加 i:= 来防止多协程冲突;实际执行任务时需要用一个函数包起来,防止单个任务panic造成整个程序崩溃。

Go

代码语言:javascript
复制
package mainimport (	"sync"
	"fmt")/*
一个标准的协程+信道实现

*/func main() {

	taskChan := make(chan int)
	TCount := 10
	var wg sync.WaitGroup //创建一个sync.WaitGroup

	// 产生任务
	go func() {		for i := 0; i < 1000; i++ {
			taskChan <- i
		}		// 全部任务都输入后关闭信道,告诉工作者进程没有新任务了。
		close(taskChan)
	}()	// 启动 TCount 个协程执行任务
	wg.Add(TCount)	for i := 0; i < TCount; i++ {		// 注意:如果协程内使用了 i,必须有这一步,或者选择通过参数传递进协程。
		// 否则 i 会被 for 所在的协程修改,协程实际使用时值并不确定。
		i := i		go func() {			// 协程结束时报告当前协程执行完毕。
			defer func() { wg.Done() }()

			fmt.Printf("工作者 %v 启动...\r\n", i)			for task := range taskChan {				// 建立匿名函数执行任务的目的是为了捕获单个任务崩溃,防止造成整个工作者、系统崩溃。
				func() {					defer func() {
						err := recover()						if err != nil {
							fmt.Printf("任务失败:工作者i=%v, task=%v, err=%v\r\n", i, task, err)
						}
					}()					// 故意崩溃,看看是不是会造成整个系统崩溃。
					if task%100==0{						panic("故意崩溃啦")
					}					// 这里的 task 并不需要通过参数传递进来。
					// 原因是这里是同步执行的,并不会被其它协程修改。
					fmt.Printf("任务结果=%v ,工作者id=%v, task=%v\r\n",task*task,i,task)
				}()
			}

			fmt.Printf("工作者 %v 结束。\r\n", i)
		}()
	}	//等待所有任务完成
	wg.Wait()	print("全部任务结束")
}
代码语言:javascript
复制
packagemainimport("sync""fmt")
 /*
一个标准的协程+信道实现
 
*/ 
funcmain(){
 
taskChan:=make(chanint)
TCount:=10varwgsync.WaitGroup//创建一个sync.WaitGroup // 产生任务gofunc(){
fori:=0;i<1000;i++{
taskChan<-i
}// 全部任务都输入后关闭信道,告诉工作者进程没有新任务了。close(taskChan)
}()
 // 启动 TCount 个协程执行任务wg.Add(TCount)
fori:=0;i<TCount;i++{
 // 注意:如果协程内使用了 i,必须有这一步,或者选择通过参数传递进协程。// 否则 i 会被 for 所在的协程修改,协程实际使用时值并不确定。i:=i
 
gofunc(){
 // 协程结束时报告当前协程执行完毕。deferfunc(){wg.Done()}()
 
fmt.Printf("工作者 %v 启动...\r\n",i)
 
fortask:=rangetaskChan{
 // 建立匿名函数执行任务的目的是为了捕获单个任务崩溃,防止造成整个工作者、系统崩溃。func(){
 
deferfunc(){
err:=recover()
iferr!=nil{
fmt.Printf("任务失败:工作者i=%v, task=%v, err=%v\r\n",i,task,err)
}
}()
 // 故意崩溃,看看是不是会造成整个系统崩溃。iftask%100==0{panic("故意崩溃啦")
}
 // 这里的 task 并不需要通过参数传递进来。// 原因是这里是同步执行的,并不会被其它协程修改。fmt.Printf("任务结果=%v ,工作者id=%v, task=%v\r\n",task*task,i,task)
}()
}
 
fmt.Printf("工作者 %v 结束。\r\n",i)
}()
}
 //等待所有任务完成wg.Wait()print("全部任务结束")
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-05-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Golang语言社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档