介紹
使用無緩沖的通道來創建一個 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\n", 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
