執行緒池ThreadPool知識碎片和使用經驗速記

weixin_34262482發表於2013-12-21

ThreadPool(執行緒池)大概的工作原理是,初始時執行緒池中建立了一些執行緒,當應用程式需要使用執行緒池中的執行緒進行工作,執行緒池將會分配一個執行緒,之後到來的請求,執行緒池都會盡量使用池中已有的這個執行緒進行響應,如果請求過多的話,執行緒池將會按照策略等待或者建立新的執行緒進行響應直到達到上限。當執行緒池中的執行緒處於空閒狀態一定時間後(具體多少看環境)執行緒池池內的空閒執行緒將會進行自我終結。

1、CLR的一個程式內會維護一個執行緒池,執行緒池被該程式內所有應用程式域共享。託管執行緒池中的執行緒為後臺執行緒, 即執行緒的IsBackground屬性為true。這意味著在所有的前臺執行緒都已退出後,ThreadPool 執行緒不會讓應用程式保持執行。

2、從.NET4.0開始,程式的執行緒池的預設大小由虛擬地址空間的大小等多個因素決定,它的預設大小為每個可用處理器250個輔助執行緒,再加上1000個I/O完成執行緒。程式可以呼叫 GetMaxThreads 方法以確定執行緒的數量。 使用 SetMaxThreads 方法可以更改執行緒池中的執行緒數。 每個執行緒使用預設的堆疊大小並按照預設的優先順序執行。

3、執行緒池分為兩類,一類是Work Thread(計算密集型),一類是IO Thread(IO密集型)。IO密集型執行緒可以在不佔用CPU的情況下通過裝置驅動程式進行IO操作,比如帶BeginXXX和Endxxx方法的檔案操作、網路訪問等方法。這種帶Begin/End的非同步操作寫法也就是熟知的Asynchronous Programming Model (APM)模式。使用APM模式,呼叫BeginInvoke卻不呼叫EndInvoke會使得執行緒資源無法回收引發memory leak,高併發條件下會造成應用程式崩潰。

4、委託的BeginInvoke方法,本質上也是通過執行緒池完成工作的,所以我們熟知的Func、Action等委託,通過BeginInvoke的方式非同步呼叫方法,必須要寫對應的callback,因為呼叫BeginInvoke卻不呼叫EndInvoke會使得執行緒資源無法回收。

5、並行開發TPL技術背後離不開ThreadPool,FCL的Task線上程池的基礎上進行了優化,並提供了更多更強大且方便的功能,如Task支援執行緒的取消、完成、失敗通知等互動性操作,以及支援執行緒執行的先後次序。

6、.NET4.5自帶的asyncawait,就是基於.NET4.0裡的Task和Parallel的再開發,歸根結底是呼叫Task的語法糖,它們的實現也離不開執行緒池在背後的工作。

7、線上程池中呼叫Thread.Sleep方法會導致該執行緒池中的某工作執行緒掛起,無法回到池中,當然無法處理其他任務,也就是說這個執行緒此時只是在休息,不能幹其他活。

8、在多執行緒、非同步及並行操作中,異常處理必須非常小心,如果不捕獲會導致該執行緒所屬程式崩潰。

 

參考:

http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx

http://msdn.microsoft.com/en-us/library/hh191443.aspx

http://www.cnblogs.com/yuyijq/category/278984.html

http://stackoverflow.com/questions/5264836/in-net-4-does-begininvoke-and-task-use-the-same-threadpool

<<CLR via C#>>

相關文章