完整的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-04-25

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏黑白安全

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

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

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

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

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

80980
来自专栏黑白安全

互联漏洞[提权挂黑]

XSS (cross-site script) 跨站脚本自1996年诞生以来,一直被OWASP(open web application security pr...

17240
来自专栏编程

NodeMCU模块写入MicroPython固件

首先到micropython官方网站下载esp8266的固件, 下载地址为: https://micropython.org/download/#esp8266...

64170
来自专栏技术博文

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

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

44040
来自专栏安恒信息

安全部门监测发现恶意后门程序新变种

国家网络安全部门通过对互联网的监测发现,近期出现一种恶意后门程序变种Backdoor_Parite.B. 该变种是一个远程控制程...

33270
来自专栏散尽浮华

centos下部署NTP时间服务器同步环境记录

1)服务端部署 安装所需软件包 [root@test ~]# yum -y install ntp ntpdate 服务端自己先手工同步一次时间。 [root...

51050
来自专栏landv

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

5.9K20
来自专栏Huramkin的归档库

在Telegram搭建一个订阅机器人

如何创建机器人自行搜索 这里我刚刚创建了个机器人@PushRss_Bot 获取到了Token 进入这个目录

1.1K20
来自专栏FreeBuf

3步以内利用中间人MitM攻击从RDP连接中获得密码

今天和大家分享个小技术,简单几步通过执行MitM攻击同时从RDP连接中提取明文凭据。我这里使用的测试环境是Linux(1台)、Windows(2台),此环境仅供...

25330

扫码关注云+社区

领取腾讯云代金券