一、線程池的概念
1、線程的創建和銷毀要付出較高的代價,頻繁創建和銷毀線程會降低系統的性能。線程池就是一些在應用程序起始時就創建好的線程,這些線程可用於執行應用程序需要的不同操作。
2、線程池為每個任務提供一個工作線程,任務執行完後工作線程的狀態會重置,以便執行下一個任務,而不是被銷毀。
3、線程池有一個任務隊列,所有等待執行的任務都進入任務隊列,在有空閑線程時會從隊列中取出一個任務執行,如果沒有空閑線程就等待直到有線程可用。
using System; using System.Threading; namespace ThreadPoolExample { class Program { static void Main(string[] args) { for (int i = 0; i < 10; i++) { ThreadPool.QueueUserWorkItem(PrintHello); } Console.ReadKey(); } private static void PrintHello(object state) { Console.WriteLine($"Hello from thread {Thread.CurrentThread.ManagedThreadId}"); } } }
二、線程池的使用
1、線程池的創建
線程池是由framework提供的,可以使用ThreadPool類的靜態方法來創建。ThreadPool.GetMaxThreads()方法返回可用於線程池的最大線程數。ThreadPool.GetAvailableThreads()方法返回線程池中空閑線程的數量。
int maxThreads; int availableThreads; ThreadPool.GetMaxThreads(out maxThreads, out availableThreads); Console.WriteLine($"Max threads: {maxThreads}. Available threads: {availableThreads}");
2、線程池的任務添加
可以使用ThreadPool.QueueUserWorkItem()方法添加任務到線程池,該方法接受一個委託作為參數,需要執行的代碼可以是匿名方法或普通方法。
ThreadPool.QueueUserWorkItem(new WaitCallback(PrintHello)); ThreadPool.QueueUserWorkItem(PrintHello);
3、線程池的工作隊列
可以使用ThreadPool.GetQueuedThreadInfo()方法獲取線程池正在排隊的工作線程的一些信息。
ThreadPool.GetQueuedThreadInfo(out int queueLength, out int workerThreads); Console.WriteLine($"Queue length: {queueLength}. Worker threads: {workerThreads}");
三、線程池的優化
1、線程池的自定義大小
線程池的大小默認是由CLR制定的,但可以通過調用ThreadPool.SetMaxThreads()和ThreadPool.SetMinThreads()方法來自定義。
ThreadPool.SetMaxThreads(4, 4); ThreadPool.SetMinThreads(2, 2);
2、使用線程池執行長時間任務
由於線程池的默認大小是有限的,如果存在一個耗時很長的任務,會佔用線程池的大部分線程,導致其他任務等待執行。
可以將長時間任務分成多個小任務,並使用非同步方式執行,以便在等待長時間任務完成時釋放線程池中的線程。
for (int i = 0; i { // DoSomeWork()是一個耗時很長的方法 var result = DoSomeWork(); // 執行完小任務之後,釋放線程池中的線程 }); }
3、避免線程池阻塞
線程池中的每個線程默認都是前台線程,會保持程序運行。當調用某些方法時,如Thread.Sleep()或 Thread.Join(),會產生阻塞線程池的效果。
為了避免線程池被阻塞,可以創建一個後台線程,代替前台線程,使用ManualResetEvent.WaitOne()方法等待。
static void Main(string[] args) { var resetEvent = new ManualResetEvent(false); var thread = new Thread(() => { // DoSomethingLong(); resetEvent.Set(); }) { IsBackground = true }; thread.Start(); resetEvent.WaitOne(); }
四、線程池使用場景
線程池適用於需要執行大量可以非同步執行的任務的情況。常見的應用包括:網路套接字通信的非同步執行、大量文件I / O非同步執行、在多個客戶端中非同步執行長時間操作以提高Web伺服器吞吐量等。
五、參考鏈接
c#線程池:https://docs.microsoft.com/en-us/dotnet/api/system.threading.threadpool?view=net-5.0
c#線程池介紹:https://www.cnblogs.com/hanyinglong/p/6913031.html
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/287350.html