爲何使用線程池? 程序員
在面向對象編程中,建立和銷燬對象是很費時間的,由於建立一個對象要獲取內存資源或者其它更多資源,因此提升服務程序效率的一個手段就是儘量減小建立和銷燬對象的次數,特別是一些很耗資源的對象建立和銷燬。如何利用已有對象來服務就是一個須要解決的關鍵問題,其實這就是一些"池化資源"技術產生的緣由。好比你們所熟悉的數據庫鏈接池正是遵循這一思想而產生的,本文將介紹的線程池技術一樣符合這一思想。算法
多線程是什麼?組成?特色?數據庫
線程池是一種多線程處理形式,處理過程當中將任務添加到隊列,而後在建立線程後自動啓動這些任務。線程池中的線程由系統管理,程序員不須要費力於線程管理,能夠集中精力處理應用程序任務。編程
特色:安全
何時使用線程池? 服務器
一、GetMaxThreads() : 獲取能夠同時處於活動狀態的線程池請求的最大數目。全部大於此數目的請求將保持排隊狀態,直到線程池線程變爲可用。多線程
參數1:workerThreads :線程池中輔助線程的最大數目。
參數2:completionPortThreads :線程池中異步 I/O 線程的最大數目。 異步
二、GetMinThreads() 獲取線程池維護的最小空閒線程數。 函數
三、SetMaxThreads() 設置能夠同時處於活動狀態的線程池的最大請求數目(不考慮計算機處理器的數目)性能
參數1:workerThreads::要由線程池維護的新的最小空閒輔助線程數。
參數2:completionPortThreads::要由線程池維護的新的最小空閒異步 I/O 線程數。
返回值:若是更改爲功,則爲 true;不然爲 false。
四、SetMinThreads() 設置線程池在新請求預測中維護的空閒線程數(不考慮計算機處理器的數目)
參數1:workerThreads:要由線程池維護的新的最小空閒輔助線程數。
參數2:completionPortThreads:要由線程池維護的新的最小空閒異步 I/O 線程數。
返回值:若是更改爲功,則爲 true;不然爲 false。
五、GetAvailableThreads() 獲取由 GetMaxThreads 返回的線程池線程的最大數目和當前活動數目之間的差值。
參數1:workerThreads:可用輔助線程的數目。
參數2:completionPortThreads:可用異步 I/O 線程的數目。
六、QueueUserWorkItem() 將方法排入隊列以便執行。此方法在有線程池線程變得可用時執行。
返回值:若是將方法成功排入隊列,則爲 true;不然爲 false。
參數2:state :包含方法所用數據的對象。
返回值:若是將方法成功排入隊列,則爲 true;不然爲 false。
備註:WaitCallback 回調方法必須與System.Threading.WaitCallback委託類型相匹配。
WaitCallback函數原型:public delegate void WaitCallback(Object state);調用QueueUserWorkItem能夠經過Object來向任務過程傳遞參數。若是任務過程須要多個參數,能夠定義包含這些數據的類,並將類的實例強制轉換爲Object數據類型。
七、UnsafeQueueUserWorkItem() 非安全性註冊一個等待 WaitHandle 的委託(將方法排入隊列以便執行)。
八、RegisterWaitForSingleObject() 將指定的委託排隊到線程池。當發生如下狀況之一時,輔助線程將執行委託。
九、UnsafeRegisterWaitForSingleObject() 非安全性將指定的委託排隊到線程池。
線程池示例?
咱們先來看一個簡單的線程實例:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Console.WriteLine("Begin in Main"); Thread t = new Thread(ThreadInvoke); t.IsBackground = true; t.Start(); //將當前線程掛起200毫秒 Thread.Sleep(200); Console.WriteLine("End in Main"); Console.ReadKey(); } static void ThreadInvoke(object obj) { for (int i = 0; i < 5; i++) { Console.WriteLine("Execute in ThreadInvoke"); //每隔100毫秒,循環一次 Thread.Sleep(100); } } } }
"End in Main"並無在ThreadInvoke()方法中全部代碼執行完以後才輸出。
因而可知Main方法和ThreadInvoke是並行執行的
使用線程池改造上邊的示例:
上面介紹了只是一個最簡單的有關線程線程的例子,但在實際開發中使用的線程每每是大量的和更爲複雜的,這時,每次都建立線程、啓動線程。從性能上來說,這樣作並不理想(由於每使用一個線程就要建立一個,須要佔用系統開銷);從操做上來說,每次都要啓動,比較麻煩。爲此引入的線程池的概念。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Console.WriteLine("Begin in Main"); ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadInvoke)); Console.WriteLine("End in Main"); //將當前線程掛起200毫秒 Thread.Sleep(3000); Console.ReadKey(); } static void ThreadInvoke(object obj) { for (int i = 0; i < 5; i++) { Console.WriteLine("Execute in ThreadInvoke"); //每隔100毫秒,循環一次 Thread.Sleep(100); } } } }
Thread.Sleep(3000)這句話是必須的由於當Main方法結束後,.Net環境會自動結束銷燬線程池,爲了保證完成線程池裏的任務,因此主線程須要等待一段時間。
由輸出結果可知,Main方法和ThreadInvoke方法是並行執行的。