使用Thread類已經可以創建並啟動線程了,但是隨著開啟的線程越來越多,線程的創建和終止都需要手動操作,非常繁瑣,另一個問題是,開啟更多新的線程但是沒有用的線程沒有及時得到終止的時候,會占用越來越多的系統資源,影響性能。 所以,.net為我們引入了ThreadPool(線程池),我們只需要把要執行的 ...
使用Thread類已經可以創建並啟動線程了,但是隨著開啟的線程越來越多,線程的創建和終止都需要手動操作,非常繁瑣,另一個問題是,開啟更多新的線程但是沒有用的線程沒有及時得到終止的時候,會占用越來越多的系統資源,影響性能。
所以,.net為我們引入了ThreadPool(線程池),我們只需要把要執行的任務放到線程池中即可,線程的開啟包括資源的釋放都由線程池幫我們完成。下麵看一下怎麼使用線程池。
線程池ThreadPool
核心類:System.Threading.ThreadPool, 線程池受.Net CLR管理的,每一個CLR都有一個線程池實例。
每個進程都有一個線程池,線程池的預設大小為:每個可用的處理器有 25 個線程。使用 SetMaxThreads 方法可以更改線程池中的線程數。每個線程使用預設的堆棧大小並按照預設的優先順序運行。
ThreadPool類型擁有一個QueueUserWorkItem的靜態方法。該靜態方法接收一個委托,代表用戶自定義的一個非同步操作。在改方法被調用後,委托會進入到內部隊列中。如果線程池中沒有任何線程,將創建一個新的工作者線程(worker thread)並將隊列中的第一個委托放入到該工作者線程中。
如果向線程池中放入新的操作,當之前的所有操作完成後,很可能只需重用一個線程來執行這些新的操作。如果QueueUserWorkItem執行的頻率過快,線程池將創建更多的線程來執行這些新放入的非同步委托。
線程池中的線程數是有限的,如果沒有空閑的線程來執行這些非同步委托操作,這種情況下,新的非同步委托操作將線上程池的內部隊列中等待,直到線程池中年的工作者線程空閑(有能力)來執行。
當停止向線程池中放入新的非同步委托操作時,線程池會刪除一定事件後過期的不在使用的線程,同時釋放不再使用的系統資源。
線程池的使用非常簡單,如下代碼:
namespace ConsoleApplication18 { class Program { static void Main(string[] args) { Console.WriteLine("Main thread starting..."); //1,不帶參數 ThreadPool.QueueUserWorkItem(AsyncAction); Thread.Sleep(TimeSpan.FromMilliseconds(3000)); //2,帶參數 ThreadPool.QueueUserWorkItem(AsyncAction, "Async state"); Thread.Sleep(TimeSpan.FromMilliseconds(3000)); //3,lambda表達式 ThreadPool.QueueUserWorkItem(item => { Console.WriteLine("Sub thread starting..."); Console.WriteLine("Action state:" + item ?? string.Empty); Console.WriteLine(string.Format("Current thread id:{0}", Thread.CurrentThread.ManagedThreadId)); }, "Lambda state"); Thread.Sleep(TimeSpan.FromMilliseconds(3000)); Console.WriteLine("Main thread completed!"); Console.ReadKey(); } /// <summary> /// 委托匹配方法 /// </summary> /// <param name="obj"></param> static void AsyncAction(Object obj) { Console.WriteLine("Sub thread starting..."); Console.WriteLine("Action state:" + obj ?? string.Empty); Console.WriteLine(string.Format("Current thread id:{0}", Thread.CurrentThread.ManagedThreadId)); } } }
輸出結果:
不適合使用線程池的場景
使用線程池創建線程這麼簡單,然後性能又好,是不是以後創建線程都去使用線程池呢?答案是否定的。
那麼,以下場景是不適合使用線程池,而是自己創建並管理線程:
- 需要前臺線程時。因為線程池預設創建的都是後臺線程。
- 需要線程具有特定的優先順序。因為放到線程池中的線程都是由線程池來調度的,無法對其優先順序進行設置。
- 需要長時間運行的任務。由於線程池具有最大線程數限制,因此大量阻塞的線程池線程可能會阻止任務啟動。