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

时间:2022-05-05
本文章向大家介绍完整的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 启动...rn", i)			for task := range taskChan {				// 建立匿名函数执行任务的目的是为了捕获单个任务崩溃,防止造成整个工作者、系统崩溃。
				func() {					defer func() {
						err := recover()						if err != nil {
							fmt.Printf("任务失败:工作者i=%v, task=%v, err=%vrn", i, task, err)
						}
					}()					// 故意崩溃,看看是不是会造成整个系统崩溃。
					if task%100==0{						panic("故意崩溃啦")
					}					// 这里的 task 并不需要通过参数传递进来。
					// 原因是这里是同步执行的,并不会被其它协程修改。
					fmt.Printf("任务结果=%v ,工作者id=%v, task=%vrn",task*task,i,task)
				}()
			}

			fmt.Printf("工作者 %v 结束。rn", 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 启动...rn",i)
 
fortask:=rangetaskChan{
 // 建立匿名函数执行任务的目的是为了捕获单个任务崩溃,防止造成整个工作者、系统崩溃。func(){
 
deferfunc(){
err:=recover()
iferr!=nil{
fmt.Printf("任务失败:工作者i=%v, task=%v, err=%vrn",i,task,err)
}
}()
 // 故意崩溃,看看是不是会造成整个系统崩溃。iftask%100==0{panic("故意崩溃啦")
}
 // 这里的 task 并不需要通过参数传递进来。// 原因是这里是同步执行的,并不会被其它协程修改。fmt.Printf("任务结果=%v ,工作者id=%v, task=%vrn",task*task,i,task)
}()
}
 
fmt.Printf("工作者 %v 结束。rn",i)
}()
}
 //等待所有任务完成wg.Wait()print("全部任务结束")
}