先上代碼,有興趣的可以跑一下
可以實現在有限的線程裏執行多個任務,控制內存使用,防止內存飆高
package main import ( "context" "fmt" "strconv" "sync" "time" ) // 定義靜態變量 用於外部訪問內部方法 var pool *_Pool // 定義空結構體,相當於類,和下面組合New方法起來就是pool類的靜態方法 type _Pool struct { } // 定義接口 可傳任意參數 type TaskFunc func(args ...interface{}) // 定義任務實體,裏面有方法和參數 type Task struct { f TaskFunc args interface{} } // 定義線程池對象 type WorkPool struct { Pool chan *Task //定義任務池 WorkCount int //工作線程數量,決定初始化幾個goroutine StopCtx context.Context //上下文 StopCancel context.CancelFunc WG sync.WaitGroup //阻塞計數器 } //任務執行 func (t *Task) Execute(args ...interface{}) { t.f(args...) } // 實例化一個新線程池 func (*_Pool) New(workerCount int, len int) *WorkPool { return &WorkPool{ WorkCount: workerCount, Pool: make(chan *Task, len), } } // 任務入隊 func (w *WorkPool) PushTask(task *Task) { w.Pool <- task } // 任務調度 go協程從channel裏取任務執行Execute方法 func (w *WorkPool) Work(wid int) { for { select { case <-w.StopCtx.Done(): w.WG.Done() fmt.Printf("線程%d 退出執行了 \n", wid) return case t := <-w.Pool: if t != nil { t.Execute() fmt.Printf("f被線程%d執行了,參數爲%v \n", wid, t.args) } } } } //啓動線程池,觸發任務調度 func (w *WorkPool) Start() *WorkPool { //定義好worker數量 w.WG.Add(w.WorkCount) w.StopCtx, w.StopCancel = context.WithCancel(context.Background()) for i := 0; i < w.WorkCount; i++ { //定義多少個協程來工作 go w.Work(i) } return w } // 停止執行任務,回收正在執行任務的協程 協程計數器減1 直到變成0退出,否則阻塞 func (w *WorkPool) Stop() { w.StopCancel() w.WG.Wait() } func main() { // 任務計數器 taskWg := sync.WaitGroup{} workerCount := 2 taskCount := 10 // 啓動線程池 len=channel通道容量,超過容量生產者阻塞,容量變成0 消費者阻塞 pool := pool.New(workerCount, 5).Start() taskWg.Add(taskCount) //構建任務 放入線程池 for i := 0; i < taskCount; i++ { task := &Task{ args: "zhangSan" + strconv.FormatInt(int64(i), 10), f: func(args ...interface{}) { time.Sleep(time.Second) taskWg.Done() // 任務完成計數器減一 }, } pool.PushTask(task) } fmt.Println("任務入隊完成") //等待任務執行完成 taskWg.Wait() // 回收資源 close(pool.Pool) fmt.Println("任務全部執行完成") }
運行效果
f被線程0執行了,參數爲zhangSan0
f被線程1執行了,參數爲zhangSan1
f被線程1執行了,參數爲zhangSan3
f被線程0執行了,參數爲zhangSan2
任務入隊完成
f被線程0執行了,參數爲zhangSan5
f被線程1執行了,參數爲zhangSan4
f被線程1執行了,參數爲zhangSan7
f被線程0執行了,參數爲zhangSan6
f被線程1執行了,參數爲zhangSan8
任務全部執行完成
裏面代碼註釋的很詳細了,就不贅述了