Golang併發模型:輕鬆入門協程池

goroutine是很是輕量的,不會暫用太多資源,基本上有多少任務,咱們能夠開多少goroutine去處理。但有時候,咱們仍是想控制一下。golang

好比,咱們有A、B兩類工做,不想把太多資源花費在B類務上,而是花在A類任務上。對於A,咱們能夠來1個開一個goroutine去處理,對於B,咱們可使用一個協程池,協程池裏有5個線程去處理B類任務,這樣B消耗的資源就不會太多。緩存

控制使用資源並非協程池目的,使用協程池是爲了更好併發、程序魯棒性、容錯性等。廢話少說,快速入門協程池纔是這篇文章的目的。bash

協程池指的是預先分配固定數量的goroutine處理相同的任務,和線程池是相似的,不一樣點是協程池中處理任務的是協程,線程池中處理任務的是線程。併發

最簡單的協程池模型

簡單協程池模型

上面這個圖展現了最簡單的協程池的樣子。先把協程池做爲一個總體看,它使用2個通道,左邊的jobCh是任務通道,任務會從這個通道中流進來,右邊的retCh是結果通道,協程池處理任務後獲得的結果會寫入這個通道。至於協程池中,有多少協程處理任務,這是外部不關心的。less

看一下協程池內部,圖中畫了5個goroutine,實際goroutine的數量是依具體狀況而定的。協程池內每一個協程都從jobCh讀任務、處理任務,而後將結果寫入到retChspa

示例

模型看懂了,看個小例子吧。線程

示例代碼1

workerPool()會建立1個簡單的協程池,協程的數量能夠通入參數n執行,而且還指定了jobChretCh兩個參數。code

worker()是協程池中的協程,入參分佈是它的ID、job通道和結果通道。使用for-rangejobCh讀取任務,直到jobCh關閉,而後一個最簡單的任務:生成1個字符串,證實本身處理了某個任務,並把字符串做爲結果寫入retCh協程

示例代碼2

main()啓動genJob獲取存聽任務的通道jobCh,而後建立retCh,它的緩存空間是200,並使用workerPool啓動一個有5個協程的協程池。1s以後,關閉retCh,而後開始從retCh中讀取協程池處理結果,並打印。隊列

genJob啓動一個協程,並生產n個任務,寫入到jobCh

示例運行結果以下,一共產生了10個任務,顯示大部分工做都被worker 2這個協程搶走了,若是咱們設置的任務成千上萬,協程池長時間處理任務,每一個協程處理的工做數量就會均衡不少。

➜ go run simple_goroutine_pool.go
worker 2 processed job: 4
worker 2 processed job: 5
worker 2 processed job: 6
worker 2 processed job: 7
worker 2 processed job: 8
worker 2 processed job: 9
worker 0 processed job: 1
worker 3 processed job: 2
worker 4 processed job: 3
worker 1 processed job: 0

回顧

最簡單的協程池模型就這麼簡單,再回頭看下協程池及周邊由哪些組成:

  1. 協程池內的必定數量的協程。
  2. 任務隊列,即jobCh,存在協程池不能當即處理任務的狀況,因此須要隊列把任務先暫存。
  3. 結果隊列,即retCh,同上,協程池處理任務的結果,也存在不能被下游馬上提取的狀況,要暫時保存。

協程池最簡要(核心)的邏輯是全部協程從任務讀取任務,處理後把結果存放到結果隊列。

Go併發系列文章

  1. Golang併發模型:輕鬆入門流水線模型
  2. Golang併發模型:輕鬆入門流水線FAN模式
  3. Golang併發模型:併發協程的優雅退出
  4. Golang併發模型:輕鬆入門select
  5. Golang併發模型:select進階
  6. Golang併發模型:輕鬆入門協程池
  1. 若是這篇文章對你有幫助,請點個贊/喜歡,鼓勵我持續分享,感謝
  2. 若是喜歡本文,隨意轉載,但請保留此原文連接
  3. 博客文章列表,點此可查看

一塊兒學Golang-分享有料的Go語言技術

相關文章
相關標籤/搜索