golang線程池【簡易版】

先上代碼,有興趣的可以跑一下

可以實現在有限的線程裏執行多個任務,控制內存使用,防止內存飆高

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 
任務全部執行完成

 

裏面代碼註釋的很詳細了,就不贅述了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章