抓蟲系列(四) 不要輕視web程序中常用的三個"池" 之線程池
2011-10-22 14:12 熬夜的蟲子 閱讀(918) 評論(2) 收藏 舉報前篇回顧:上篇講了數據庫連接池的問題,其實關于是否是活動連接還是有很大問題可以挖掘的。這個有空蟲子再和大家交流了
本篇談下線程池的相關問題,希望各位看官留個爪印,應用程序池和數據庫連接池可能大部分程序員不需要關心那個,不過線程池可所謂是重頭戲了。
先把蟲子的觀點放上: 個人表示排斥在項目中使用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);
}

至于還有哪些,大家可以各自討論,或者提出反對的意見。
![]() |
原創作品允許轉載,轉載時請務必以超鏈接形式標明文章原始出處以及作者信息。 作者:熬夜的蟲子 點擊查看:博文索引 |

浙公網安備 33010602011771號