介绍
使用无缓冲的通道来创建一个 goroutine 池,这些 goroutine 执行并控制一组工作,让其并发执行。在这种情况下,使用无缓冲的通道要比随意指定一个缓冲区大小的有缓冲的通道好,因为这个情况下既不需要一个工作队列,也不需要一组 goroutine 配合执行。这种使用无缓冲的通道的方法允许使用者知道什么时候 goroutine 池正在执行工作,而且如果池里的所有goroutine 都忙,无法接受新的工作的时候,也能及时通过通道来通知调用者。使用无缓冲的通道不会有工作在队列里丢失或者卡住,所有工作都会被处理。
程序
work.go
package work import ( "sync" ) //任务类型接口 type Worker interface { Task(goid int) } //任务池 type Pool struct { work chan Worker wg sync.WaitGroup } //新建 func New(maxGoroutines int) *Pool { //任务池 p := Pool{ work: make(chan Worker), } p.wg.Add(maxGoroutines) //创建maxGoroutines个go协程 for i := 0; i < maxGoroutines; i++ { go func(goid int) { //保证goroutine不停止执行通道中的任务 for w := range p.work { w.Task(goid) } //每个goroutine不再执行work通道中任务时停止 p.wg.Done() }(i) } return &p } //运行 func (p *Pool) Run(r Worker) { p.work <- r } //停止 func (p *Pool) Shutdown() { close(p.work) p.wg.Wait() }
main.go
package main import ( "gopro/patterns/work" "log" "sync" "time" ) // var names = []string{ "lili", "yingying", } //Worker实现类型 type namePrinter struct { name string } func (n *namePrinter) Task(goid int) { log.Printf("goroutineID:%d,打印名字为:%s ", goid, n.name) time.Sleep(time.Second) } func main() { p := work.New(3) var wg sync.WaitGroup wg.Add(10 * len(names)) for i := 0; i < 10; i++ { for _, name := range names { //任务实例 np := namePrinter{ name: name, } go func() { p.Run(&np) wg.Done() }() } } wg.Wait() p.Shutdown() }
执行结果
2019/06/22 22:55:44 goroutineID:1,打印名字为:lili 2019/06/22 22:55:44 goroutineID:0,打印名字为:yingying 2019/06/22 22:55:44 goroutineID:2,打印名字为:yingying 2019/06/22 22:55:45 goroutineID:0,打印名字为:yingying 2019/06/22 22:55:45 goroutineID:2,打印名字为:lili 2019/06/22 22:55:45 goroutineID:1,打印名字为:lili 2019/06/22 22:55:46 goroutineID:0,打印名字为:yingying 2019/06/22 22:55:46 goroutineID:2,打印名字为:yingying 2019/06/22 22:55:46 goroutineID:1,打印名字为:lili 2019/06/22 22:55:47 goroutineID:2,打印名字为:yingying 2019/06/22 22:55:47 goroutineID:1,打印名字为:lili 2019/06/22 22:55:47 goroutineID:0,打印名字为:lili 2019/06/22 22:55:48 goroutineID:1,打印名字为:lili 2019/06/22 22:55:48 goroutineID:0,打印名字为:yingying 2019/06/22 22:55:48 goroutineID:2,打印名字为:yingying 2019/06/22 22:55:49 goroutineID:2,打印名字为:lili 2019/06/22 22:55:49 goroutineID:0,打印名字为:yingying 2019/06/22 22:55:49 goroutineID:1,打印名字为:lili 2019/06/22 22:55:50 goroutineID:0,打印名字为:lili 2019/06/22 22:55:50 goroutineID:1,打印名字为:yingying