線程的建立和銷毀都要耗費大量的時間,有什麼更好的辦法?用線程池!
太多的線程浪費記憶體資源,有什麼更好的辦法?用線程池!
太多線程有損效能,有什麼更好的辦法?用線程池!(⊙_⊙)?
線程池是什嗎?繼前三篇線程基礎之後,我們要來學學線程池了。注意,這些資訊相當有用!
為了設計和實現可伸縮的、可響應的和可靠的應用程式或組建,線程池是你必須採用的核心技術。
線程池是CLR的,線程池自動為你管理線程的建立和銷毀,線程池建立的一組線程將為各種任務而重用,極大提高了使用線程的成本,這也就意味著,你的應用程式其實只需要幾個線程即可完成全部工作。
大概的講了一下,來看看線程池的細節:
大家可以想象一下:一個應用程式就好比一個抽屜,抽屜裡面放了你分好類的東西,抽屜裡面的"某一個東西"就好比這個應用程式的線程集合,這個抽象集合就是一個CLR。假如要搶救財物,你會選擇拿抽屜裡的東西還是拿抽屜呢?
好了,有了模型就好介紹CLR了,每個CLR都有它自己的線程池,這個線程池在應用程式定義域中共用。如果一個進程中載入了多了CLR,那麼每個CLR都有它自己的線程池,有點抽象(─.─|||,很難解釋清楚- -。多看幾次,會領會這個意思的。)
CLR在初始化的時候,線程池中沒有是線程的。它的內部,線程池維護著一個操作請求隊列。在應用程式想執行一個非同步作業時,就會有發送一個需要調用某個方法的”記錄項“,這個“記錄項”會追加到線程池的隊列中,然後線程池的代碼從這個記錄項中提取記錄,為記錄項分配給一個線程池線程。如果線程池中沒有線程,就建立一個新的線程。
建立線程會消耗一些資源(前面提到過了),當線程完成任務之後,線程不會被銷毀,它從哪裡來回哪裡去(回到線程池,在那裡進入空閑狀態,等待下一次命令),由於線程不會被銷毀,所以不再產生額外的效能損失。
現在疑問來了!如果應用程式發出許多請求,會怎麼辦?
線程池會嘗試只用一個線程來服務所有的請求。然而,如果應用程式發出請求的速度超過了線程池處理它們的速度,線程池就會十分人性話的加”僱用兵“,建立額外的線程。到最後,應用程式的有請求都能由少量線程處理,不會存在太多的線程,不會浪費額外的效能。
現在我們又會覺得,如果線程池真的有很多“僱傭兵”了,怎麼辦? 不照樣是浪費了嗎?
其實這個已經考慮了,一個“僱傭兵”太久接不到活怎麼辦?閒置線程多了,線程會自己醒來,來終止自己以釋放資源。
不是吧?終止線程也會產生效能損失啊!說好的解決效能損失呢??
哈哈,線程閑的蛋疼了,還有什麼效能損失?這表明應用程式已經沒有在做什麼事情了,所以這個效能損失,問題不大。
再來扯扯線程池概念,讓大家易於理解。
線程池可以只容納少量線程,從而避免資源浪費;也可以容納更多線程,以利用多處理器,超執行緒處理器和多核處理器。它能在這兩種不同的狀態之間從容切換。
線程池是啟發學習法的。只要硬體支援,比如有多個CPU,線程池就會建立更多的線程。如果應用程式的負載減輕,線程池線程就會終結它們自己。
線程池講自己的線程劃分為工作者線程和I/O線程。工作者線程是執行非同步作業的執行線程,而I/O線程則用於通知你一個非同步作業任務已經完成。
寫了一大串概念性的東西,來使用一下線程池吧^_^。
初用線程池,執行簡單的計算限制操作:
1 static void Main(string[] args) 2 { 3 Console.WriteLine("主線程啟動"); 4 ThreadPool.QueueUserWorkItem(StartCode,5); 5 Console.WriteLine("主線程運行到此!"); 6 Thread.Sleep(1000); 7 } 8 9 private static void StartCode(object i)10 {11 Console.WriteLine("開始執行子線程...{0}",i);12 Thread.Sleep(1000);//類比代碼操作13 14 15 }
這個和第一篇的那個列子很相似。也很簡單。要說的是,QueueUserWorkItem()中的參數:
必須匹配這個委託,我這個樣本是用的第二個方法。
結果就像這樣:
我的是雙核處理器,主線程和子線程是同時啟動並執行。
如果是單核的話,結果可能就不同了,因為這是Windows調試器決定先調度哪個線程式控制制不了~~~~
這主要介紹線程池,就這麼多了。^_^