技術實踐——教你用100行寫一個 go 的協程池 (任務池)!!!
點選這裡,檢視封裝 GetCap() 方法等重要內容
實現
Talk is cheap. Show me the code.
任務的定義
任務要包含需要執行的函式、以及函式要傳的引數, 因為引數型別、個數不確定, 這裡使用可變引數和空介面的形式
type Task struct {
Handler func(v ...interface{})
Params []interface{}
}
任務池的定義
任務池的定義包括了池的容量 capacity、當前執行的 worker(goroutine)數量 runningWorkers、任務佇列(channel)taskC、關閉任務池的 channel closeC 以及任務池的狀態 state(執行中或已關閉, 用於安全關閉任務池)
type Pool struct {
capacity uint64
runningWorkers uint64
state int64
taskC chan *Task
closeC chan bool
}
任務池的建構函式:
var ErrInvalidPoolCap = errors.New("invalid pool cap")
const (
RUNNING = 1
STOPED = 0
)
func NewPool(capacity uint64) (*Pool, error) {
if capacity <= 0 {
return nil, ErrInvalidPoolCap
}
return &Pool{
capacity: capacity,
state: RUNNING,
// 初始化任務佇列, 佇列長度為容量
taskC: make(chan *Task, capacity),
closeC: make(chan bool),
}, nil
}
啟動 worker
新建 run() 方法作為啟動 worker 的方法:
func (p *Pool) run() {
p.runningWorkers++ // 執行中的任務加一
go func() {
defer func() {
p.runningWorkers-- // worker 結束, 執行中的任務減一
}()
for {
select { // 阻塞等待任務、結束訊號到來
case task, ok :=
上述程式碼中, runningWorkers 的加減直接使用了自增運算, 但是考慮到啟動多個 worker 時, runningWorkers 就會有資料競爭, 所以我們使用 sync.atomic 包來保證 runningWorkers 的自增操作是原子的。
對 runningWorkers 的操作進行封裝:
func (p *Pool) incRunning() { // runningWorkers + 1
atomic.AddUint64(&p.runningWorkers, 1)
}
func (p *Pool) decRunning() { // runningWorkers - 1
atomic.AddUint64(&p.runningWorkers, ^uint64(0))
}
func (p *Pool) GetRunningWorkers() uint64 {
return atomic.LoadUint64(&p.runningWorkers)
}
打鐵乘熱, 對於 capacity 的操作也考慮資料競爭, 封裝 GetCap() 方法:
關鍵字:網路協議 Java Go
相關文章
- Go實戰準備工作---建立協程池和定時任務Go
- go 任務池Go
- Go實戰準備工作---建立攜程池和定時任務Go
- 任務池
- go 協程初體驗 [模擬使用者執行緒池,處理 50 個任務 jobs]Go執行緒
- Golang協程池(workpool)實現Golang
- ants——Go語言的高效能協程池Go
- JavaScript 任務池JavaScript
- 技術實踐:教你用Python搭建gRPC服務PythonRPC
- 看別個的協程池自己練了下
- golang協程池設計Golang
- Mix XWP V1.1 - Go 通用動態協程池 WorkerPoolGo
- 從入門到掉坑:Go 記憶體池/物件池技術介紹Go記憶體物件
- 物件池技術和通用實現GenericObjectPool物件Object
- jdk排程任務執行緒池ScheduledThreadPoolExecutor工作原理解析JDK執行緒thread
- ants - 目前開源最優的協程池
- 基於 swoole 協程的 MySQL 連線池MySql
- 池化技術總結
- Istio技術與實踐04:最佳實踐之教你寫一個完整的Mixer AdapterAPT
- Unity寫個多用物件池Unity物件
- 手寫一個執行緒池,帶你學習ThreadPoolExecutor執行緒池實現原理執行緒thread
- 自定義物件池實踐物件
- Swoole 實戰:MySQL 查詢器的實現(協程連線池版)MySql
- Go程式設計模式三—Fan-Out模式與協程池結合Go程式設計設計模式
- Springboot非同步任務執行緒池Spring Boot非同步執行緒
- Java BasePooledObjectFactory 物件池化技術JavaObject物件
- go的協程及channel與web開發的一點小實踐GoWeb
- 實現一個redis連線池Redis
- Scheduled 執行緒池實踐執行緒
- java執行緒池實踐Java執行緒
- 學習之路 / goroutine 併發協程池設計及實現Go
- Java GenericObjectPool 物件池化技術--SpringBoot sftp 連線池工具類JavaObject物件Spring BootFTP
- JAVA執行緒池原理原始碼解析—為什麼啟動一個執行緒池,提交一個任務後,Main方法不會退出?Java執行緒原始碼AI
- 基於Azkaban的任務定時排程實踐
- 從容器化到資源池化,數棧雲原生技術實踐探索之路
- Spring Boot使用執行緒池處理事務任務Spring Boot執行緒
- Go語言之從0到1實現一個簡單的Redis連線池GoRedis
- [譯] part23: 緩衝channel和協程池