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

有几个地方需要注意:for i + 协程时如果协程使用可 i ,那么需要增加 i:= 来防止多协程冲突;实际执行任务时需要用一个函数包起来,防止单个任务panic造成整个程序崩溃。

Go

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("全部任务结束")
}
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("全部任务结束")
}

原文发布于微信公众号 - Golang语言社区(Golangweb)

原文发表时间:2017-05-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏有趣的Python和你

记爬虫小分队(二)总结TeamViewer远程

14230
来自专栏landv

华为交换机批量加入 Vlan 方法

5.2K20
来自专栏编程思想之路

Android蓝牙配对弹出框过程分析 Android蓝牙配对弹出框过程分析

Android蓝牙配对弹出框过程分析 根据远程蓝牙设备(remote devices)的要求,手机端发起与远程蓝牙设备Bluetooth remote ...

49490
来自专栏黑白安全

黑客组织“隐匿者”技术升级再次暴力威胁入侵全网用户

区块链安全咨询公司 曲速未来 表示:"隐匿者"最早出现在2014年,此后一直从事入侵服务器或者个人主机的黑色产业,他们通过植入后门程序控制这些设备(肉鸡),然后...

27260
来自专栏游戏杂谈

手工编译Flex SDK 3.4的多国语言包

默认的Flex sdk 3.4只提供了日文(ja_JP)、英文语言包(en_US),如图所示:

11420
来自专栏更流畅、简洁的软件开发方式

js的动态加载、缓存、更新以及复用(四)

  本来想一气呵成,把加载的过程都写了,但是卡着呢,所以只好在分成两份了。   1、页面里使用<script>来加载 boot.js 。   2、然后在boot...

72480
来自专栏FreeBuf

绿盟科技威胁分析报告:那些年,那些 Apache Struts2 的漏洞

每次 Apache Struts2 漏洞爆发都在互联网上掀起腥风血雨,我们整理了近年来 Apache Struts2 高风险漏洞的信息供大家参考。针对此次 Ap...

309100
来自专栏技术博文

linux系统修改时区,时间自动同步

1、调整时区     cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime linux提供是依据/etc/lo...

41940
来自专栏后台全栈之路

U-boot两个修改:ARP支持和UDP校验支持

本文章采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。

15630
来自专栏Golang语言社区

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

有几个地方需要注意:for i + 协程时如果协程使用可 i ,那么需要增加 i:= 来防止多协程冲突;实际执行任务时需要用一个函数包起来,防止单个任务pani...

33870

扫码关注云+社区

领取腾讯云代金券