當代量產型製造業幾乎都是採用生產線作業,以汽車為例,會分成焊接、烤潻、組裝、測試等站,各站依處理時間調整人力與設備數量,以求站與站之間能無縫接軌,將閒置及等待時間降到最低,達到最大產能。而我們開發系統時,若遇到包含多個步驟的大量批次作業,每個步驟具有一定複雜度、涉及資源不一,此時就可借用生產線概念,實作成「生產者 vs 消費者」模式,追求最佳處理效能。
生產者消費者模式是電腦處理多步驟處理程序常用的軟體設計模式,也是作業系統課程一定會講到的觀念。在這個模式中,將處理動作分為「生產者」與「消費者」,前者會產出半成品或成品,由後者接手後續運用,例如:
任務 | 生產者 | 消費者 |
---|---|---|
資料爬蟲 | 關鍵字搜索、下載內容 (網路 I/O) | 內容分析 (CPU 運算) |
照片匯入資料庫 | 識別日期、尺寸縮放、產生縮圖 (CPU 運算) | 寫入資料庫 (磁碟 I/O) |
在以上兩個案例中,性質相關的動作會歸在一起,方便資源調配,例如:下載內容常需等待網路傳回結果但不耗 CPU,我們可以多開幾條執行緒提高抓取速度;內容分析很吃 CPU,可依 CPU 核數決定執行緒數量使產能最大化。寫資料庫為循序作業假設每秒可寫入一筆,但圖檔處理吃 CPU 四秒才能完成一張,故生產者端可開四條執行緒平均每秒產生一張照片,以便與消費者的消化速度完美銜接。
生產者與消費者間需要一條 Queue,讓生產者將資料有效率且可靠地交給消費者接手處理,這條 Queue 最好能具備以下功能:
關於這個議題,推薦 MVP 安德魯這篇生產者 vs 消費者 - BlockQueue 實作,裡面對生產者消費者概念有更詳細的說明,其中還自己實作了滿足上述理想的 BlockQueue 物件。
有個好消息,.NET Framework 4 之後,.NET 加入了 BlockingCollection<T>,實作生產者消費者模式不需再花功夫自己寫,用專為生產者消費者設計的 BlockingQueue 即可輕鬆搞定。
BlockingCollection 提供以下功能:(參考:BlockingCollection Overview)
下面來段範例程式感受一下它的好用。
詳情請前往原文出處 黑暗執行緒