前篇回顧:上篇講了數據庫連接池的問題,其實關於是否是活動連接還是有很大問題可以挖掘的。這個有空蟲子再和大家交流了
本篇談下線程池的相關問題,希望各位看官留個爪印,應用程序池和數據庫連接池可能大部分程序員不需要關心那個,不過線程池可所謂是重頭戲了。
先把蟲子的觀點放上: 個人表示排斥在項目中使用ThreadPool這個類,至於.net中關聯到ThreadPool的資源我們暫且不做討論。如果需要操作線程池可以使用第三方例如SmartThreadPool或者自己按照自己的項目需求開發一個。
線程池的相關概念我就不多說了,同樣這裏我只介紹下。線程池中容易被忽視的問題。
一. 相對池外線程,池內線程操作的性能極差!
ManualResetEvent[] MR = new ManualResetEvent[10]; for (int i = 0; i < 10; i++) { MR[i] = new ManualResetEvent(false); } int a, b; ThreadPool.GetMaxThreads(out a, out b); Console.WriteLine(string.Format("(輔助線程的最大數目{0} I/O線程的最大數目{1}) 初始狀態", a, b)); ThreadPool.GetAvailableThreads(out a, out b); Console.WriteLine(string.Format("(可用輔助線程的最大數目{0} 可用I/O線程的最大數目{1}) 初始狀態", a, b)); Stopwatch sw = Stopwatch.StartNew(); for (int i = 0; i < 10; i++) { new Thread((qq) => { Console.WriteLine("這是個線程池外的線程"+qq.ToString()); MR[(int)qq].Set(); Thread.Sleep(5000); }) { }.Start(i); } WaitHandle.WaitAll(MR); Console.WriteLine("生成池外10個線程 共耗時" + sw.ElapsedMilliseconds); foreach (ManualResetEvent me in MR) { me.Reset(); } Thread.Sleep(500); ThreadPool.GetAvailableThreads(out a, out b); Console.WriteLine(string.Format("(可用輔助線程的最大數目{0} 可用I/O線程的最大數目{1}) 線程池外啓動線程後", a, b)); sw = Stopwatch.StartNew(); for (int i = 0; i < 10; i++) { ThreadPool.QueueUserWorkItem(qq => { Console.WriteLine("這是個線程池內的線程" + qq.ToString()); MR[(int)qq].Set(); Thread.Sleep(20000); },i); } WaitHandle.WaitAll(MR); Console.WriteLine("生成池內10個線程 共耗時" + sw.ElapsedMilliseconds); Thread.Sleep(6000); ThreadPool.GetAvailableThreads(out a, out b); Console.WriteLine(string.Format("(可用輔助線程的最大數目{0} 可用I/O線程的最大數目{1}) 線程池內啓動線程後", a, b));
在初始狀態後 生成線程的效率存在百倍的差距!!!不過線程池既然是池的作用那麼在程序運行中應該會好很多。
二。線程池內的線程只能是後臺線程。
三。不能爲線程設置優先級。在高精度的項目中線程池不適用。
四。所支持的Callback不能有返回值。WaitCallback只能帶一個object類型的參數,沒有任何返回值。
五。容易被幹擾,同時容易破壞項目的應用環境。舉些例子
static void Main(string[] args) { //哪些函數會影響線程池 int a, b; Timer timer = new Timer((qq) => { Console.WriteLine("這是一個timer"); Thread.Sleep(2000); }, null, 2000, 1000); ThreadPool.GetAvailableThreads(out a, out b); Console.WriteLine(string.Format("(可用輔助線程的最大數目{0} 可用I/O線程的最大數目{1}) Timer啓動後", a, b)); timer.Dispose(); timer = new Timer((qq) => { ThreadPool.GetAvailableThreads(out a, out b); Console.WriteLine(string.Format("(可用輔助線程的最大數目{0}/可用I/O線程的最大數目{1}) Timer資源佔用ing", a, b)); }, null, 2000, 1000); var act = new Action(testmethod); var qqt = act.BeginInvoke(CallbackMethod, act); Console.ReadLine(); } static void CallbackMethod(IAsyncResult ar) { var caller = (Action)ar.AsyncState; caller.EndInvoke(ar); Console.WriteLine("Action回調結束"); } static void testmethod() { Console.WriteLine("Action開始"); int a, b; ThreadPool.GetAvailableThreads(out a, out b); Console.WriteLine(string.Format("(可用輔助線程的最大數目{0} 可用I/O線程的最大數目{1}) Action啓動ing", a, b)); Thread.Sleep(2000); }
至於還有哪些,大家可以各自討論,或者提出反對的意見。