Golang并发模型:轻松入门协程池
goroutine是非常輕量的,不會暫用太多資源,基本上有多少任務,我們可以開多少goroutine去處理。但有時候,我們還是想控制一下。
比如,我們有A、B兩類工作,不想把太多資源花費在B類務上,而是花在A類任務上。對于A,我們可以來1個開一個goroutine去處理,對于B,我們可以使用一個協程池,協程池里有5個線程去處理B類任務,這樣B消耗的資源就不會太多。
控制使用資源并不是協程池目的,使用協程池是為了更好并發、程序魯棒性、容錯性等。廢話少說,快速入門協程池才是這篇文章的目的。
協程池指的是預先分配固定數量的goroutine處理相同的任務,和線程池是類似的,不同點是協程池中處理任務的是協程,線程池中處理任務的是線程。
最簡單的協程池模型
上面這個圖展示了最簡單的協程池的樣子。先把協程池作為一個整體看,它使用2個通道,左邊的jobCh是任務通道,任務會從這個通道中流進來,右邊的retCh是結果通道,協程池處理任務后得到的結果會寫入這個通道。至于協程池中,有多少協程處理任務,這是外部不關心的。
看一下協程池內部,圖中畫了5個goroutine,實際goroutine的數量是依具體情況而定的。協程池內每個協程都從jobCh讀任務、處理任務,然后將結果寫入到retCh。
示例
模型看懂了,看個小例子吧。
workerPool()會創建1個簡單的協程池,協程的數量可以通入參數n執行,并且還指定了jobCh和retCh兩個參數。
worker()是協程池中的協程,入參分布是它的ID、job通道和結果通道。使用for-range從jobCh讀取任務,直到jobCh關閉,然后一個最簡單的任務:生成1個字符串,證明自己處理了某個任務,并把字符串作為結果寫入retCh。
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回顧
最簡單的協程池模型就這么簡單,再回頭看下協程池及周邊由哪些組成:
協程池最簡要(核心)的邏輯是所有協程從任務讀取任務,處理后把結果存放到結果隊列。
Go并發系列文章
總結
以上是生活随笔為你收集整理的Golang并发模型:轻松入门协程池的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IPv6关键技术之IPv6路由技术
- 下一篇: 我的世界马怎么驯服