背景
之前接手一個項目的時候,發現到處是
new?Thread(()=>{
//do?something
}).Start();
這么做的目的,無非是為了減少頁面等待時間提高用戶體驗,把一些浪費時間的操作放到新線程中在后臺運行。
問題
但是這樣帶來的問題是大量的創建線程,非常影響項目的性能,尤其是在一些大并發量訪問的時候,經常導致后果是cpu 100%。
當然,如果你的項目到處是這樣寫的,然后,沒掛,至少說明這個方法沒幾個人再用。
解決方法
于是下意識的想著給項目優化下, 第一想法是走隊列,但是發現項目壓根沒有使用隊列,很多操作還停留在 有個任務表,有任務的時候,往里面加內容,然后有個定時任務,每分鐘執行一次,定時的去消費任務;
于是想著怎么先最少的改動,先把問題解決,后面的事情在做考慮。
其實問題的本質是new 太多Thread了,那么最簡單的方法就是限制數量。
于是 ThreadPool.QueueUserWorkItem就登場了。
對于線程隊列 ThreadPool.QueueUserWorkItem 很多人應該都不陌生,下邊看微軟的解釋:
將方法排入隊列以便執行,并指定包含該方法所用數據的對象。此方法在有線程池線程變得可用時執行。
方法如下
protected?static?Logger?Logger?=?LogManager.GetCurrentClassLogger();public?ActionResult?Index(){//??Logger.Debug("執行了??開始?");ThreadPool.QueueUserWorkItem(new?WaitCallback(InsertNewsInfoExt),?"param");//???Logger.Debug("執行了??結束?");return?View();}private?void?InsertNewsInfoExt(object?info){//???Logger.Debug("執行了??InsertNewsInfoExt??開始");Thread.Sleep(1000*200);Logger.Debug("執行了??InsertNewsInfoExt?結束?");new?Thread(t?=>{try{Logger.Debug("執行了??Thread?");}catch?(Exception?ex){Logger.Error(ex.Message);}}).Start();}
根據msdn描述:線程池的默認大小為每個可用處理器有 25 個線程。使用 SetMaxThreads 方法可以更改線程池中的線程數
//工作者線程最大數目,I/O線程的最大數目ThreadPool.SetMaxThreads(1000,?1000);???//啟動工作者線程ThreadPool.QueueUserWorkItem(new?WaitCallback(InsertNewsInfoExt),?"param");
相關參數
GetAvailableThreads 剩余空閑線程數
GetMaxThreads 最多可用線程數,所有大于此數目的請求將保持排隊狀態,直到線程池線程變為可用
GetMinThreads 檢索線程池在新請求預測中維護的空閑線程數。
QueueUserWorkItem 啟動線程池里得一個線程(隊列的方式,如線程池暫時沒空閑線程,則進入隊列排隊)
SetMaxThreads 設置線程池中的最大線程數
SetMinThreads 設置線程池最少需要保留的線程數
這樣就解決了無限制 new Thread 的問題,實現了最少改動。