慎用.NET2.0 ThreadPool
在一般观念中,ThreadPool管理了一些预先初始化好的线程,ThreadPool接受任务后,多数情况下能省去了线程创建的开销,更快地开始执行。但.NET 2.0 ThreadPool的表现也许和您的期望有所差距。下面的程序专门测试ThreadPool从接受任务到开始执行的时间延迟:
测试1:并发创建10个sleep 500ms的任务,对比ThreadPool启动时间延迟和创建新线程的时间延迟。注:ThreadPool最小空闲线程数设为10。
2 {
3 ThreadPool.SetMinThreads(10, 1000);
4
5 List<Stopwatch> watches = new List<Stopwatch>();
6
7 for (int i = 0; i < 10; i++)
8 {
9 watches.Add(new Stopwatch());
10 watches[i].Start();
11
12 ThreadPool.QueueUserWorkItem(delegate(object obj)
13 {
14 int id = (int)obj;
15
16 watches[id].Stop();
17
18 Console.WriteLine("Pool Thread {0}, start delay: {1}ms", id, watches[id].ElapsedMilliseconds);
19
20 Thread.Sleep(500);
21 }, i);
22 }
23
24 Thread.Sleep(5 * 1000);
25
26 Console.WriteLine("Press Key to Continue Test
");27
28 Console.ReadLine();
29
30 watches.Clear();
31 for (int i = 0; i < 10; i++)
32 {
33 watches.Add(new Stopwatch());
34
35 watches[i].Start();
36
37 Thread thread = new Thread(delegate(object obj)
38 {
39 int id = (int)obj;
40
41 watches[id].Stop();
42
43 Console.WriteLine("Create New Thread {0}, start delay: {1}ms", id, watches[id].ElapsedMilliseconds);
44
45 Thread.Sleep(500);
46 });
47
48 thread.Start(i);
49 }
50
51
52 Console.ReadLine();
53 }
结果1:
Pool Thread 0, start delay: 6ms
Pool Thread 2, start delay: 9ms
Pool Thread 1, start delay: 5ms
Pool Thread 3, start delay: 508ms
Pool Thread 4, start delay: 508ms
Pool Thread 5, start delay: 509ms
Pool Thread 6, start delay: 1005ms
Pool Thread 7, start delay: 1008ms
Pool Thread 8, start delay: 1008ms
Pool Thread 9, start delay: 1009ms
Press Key to Continue Test...
Create New Thread 0, start delay: 25ms
Create New Thread 1, start delay: 25ms
Create New Thread 2, start delay: 5ms
Create New Thread 3, start delay: 4ms
Create New Thread 4, start delay: 4ms
Create New Thread 5, start delay: 5ms
Create New Thread 6, start delay: 4ms
Create New Thread 7, start delay: 3ms
Create New Thread 8, start delay: 3ms
Create New Thread 9, start delay: 3ms
怎么样,是不是很让人惊讶,ThreadPool的任务启动延迟居然到了1000ms左右!?最少也是6ms,而新线程方式的任务启动延迟一般才5ms左右。另外,ThreadPool的SetMinThreads似乎不起作用,前面3个任务启动在几ms,我期望的是10个都应该启动很快。
测试2: 并发创建10个sleep 10ms的任务,对比ThreadPool启动时间延迟和创建新线程的时间延迟。注:ThreadPool最小空闲线程数设为10。
2 {
3 ThreadPool.SetMinThreads(10, 1000);
4
5 List<Stopwatch> watches = new List<Stopwatch>();
6
7 for (int i = 0; i < 10; i++)
8 {
9 watches.Add(new Stopwatch());
10 watches[i].Start();
11
12 ThreadPool.QueueUserWorkItem(delegate(object obj)
13 {
14 int id = (int)obj;
15
16 watches[id].Stop();
17
18 Console.WriteLine("Pool Thread {0}, start delay: {1}ms", id, watches[id].ElapsedMilliseconds);
19
20 Thread.Sleep(10);
21 }, i);
22 }
23
24 Thread.Sleep(5 * 1000);
25
26 Console.WriteLine("Press Key to Continue Test
");27
28 Console.ReadLine();
29
30 watches.Clear();
31 for (int i = 0; i < 10; i++)
32 {
33 watches.Add(new Stopwatch());
34
35 watches[i].Start();
36
37 Thread thread = new Thread(delegate(object obj)
38 {
39 int id = (int)obj;
40
41 watches[id].Stop();
42
43 Console.WriteLine("Create New Thread {0}, start delay: {1}ms", id, watches[id].ElapsedMilliseconds);
44
45 Thread.Sleep(10);
46 });
47
48 thread.Start(i);
49 }
50
51
52 Console.ReadLine();
53 }
结果2:
Pool Thread 0, start delay: 1ms
Pool Thread 2, start delay: 29ms
Pool Thread 3, start delay: 29ms
Pool Thread 1, start delay: 28ms
Pool Thread 4, start delay: 39ms
Pool Thread 5, start delay: 39ms
Pool Thread 6, start delay: 40ms
Pool Thread 7, start delay: 40ms
Pool Thread 8, start delay: 49ms
Pool Thread 9, start delay: 49ms
Press Key to Continue Test...
Create New Thread 0, start delay: 9ms
Create New Thread 1, start delay: 10ms
Create New Thread 2, start delay: 11ms
Create New Thread 3, start delay: 3ms
Create New Thread 4, start delay: 3ms
Create New Thread 5, start delay: 3ms
Create New Thread 6, start delay: 3ms
Create New Thread 8, start delay: 46ms
Create New Thread 7, start delay: 97ms
Create New Thread 9, start delay: 90ms
这次ThreadPool延迟没有那么大,看来延迟和任务执行时间也有关系,如果ThreadPool中有长任务,会影响到后来任务的启动延迟。
测试3:依次创建10个sleep 500ms的任务,对比ThreadPool启动时间延迟和创建新线程的时间延迟。注:ThreadPool最小空闲线程数设为10。
2 {
3 ThreadPool.SetMinThreads(10, 1000);
4
5 List<Stopwatch> watches = new List<Stopwatch>();
6
7 for (int i = 0; i < 10; i++)
8 {
9 watches.Add(new Stopwatch());
10 watches[i].Start();
11
12 ThreadPool.QueueUserWorkItem(delegate(object obj)
13 {
14 int id = (int)obj;
15
16 watches[id].Stop();
17
18 Console.WriteLine("Pool Thread {0}, start delay: {1}ms", id, watches[id].ElapsedMilliseconds);
19
20 Thread.Sleep(500);
21 }, i);
22
23 Thread.Sleep(500); //依次创建线程
24 }
25
26 Thread.Sleep(5 * 1000);
27
28 Console.WriteLine("Press Key to Continue Test
");29
30 Console.ReadLine();
31
32 watches.Clear();
33 for (int i = 0; i < 10; i++)
34 {
35 watches.Add(new Stopwatch());
36
37 watches[i].Start();
38
39 Thread thread = new Thread(delegate(object obj)
40 {
41 int id = (int)obj;
42
43 watches[id].Stop();
44
45 Console.WriteLine("Create New Thread {0}, start delay: {1}ms", id, watches[id].ElapsedMilliseconds);
46
47 Thread.Sleep(500);
48 });
49
50 thread.Start(i);
51
52 Thread.Sleep(500); //依次创建线程
53 }
54
55
56 Console.ReadLine();
57 }
结果2:
Pool Thread 0, start delay: 1ms
Pool Thread 1, start delay: 2ms
Pool Thread 2, start delay: 0ms
Pool Thread 3, start delay: 0ms
Pool Thread 4, start delay: 0ms
Pool Thread 5, start delay: 0ms
Pool Thread 6, start delay: 0ms
Pool Thread 7, start delay: 0ms
Pool Thread 8, start delay: 0ms
Pool Thread 9, start delay: 0ms
Press Key to Continue Test...
Create New Thread 0, start delay: 3ms
Create New Thread 1, start delay: 2ms
Create New Thread 2, start delay: 1ms
Create New Thread 3, start delay: 1ms
Create New Thread 4, start delay: 1ms
Create New Thread 5, start delay: 1ms
Create New Thread 6, start delay: 1ms
Create New Thread 7, start delay: 1ms
Create New Thread 8, start delay: 1ms
Create New Thread 9, start delay: 2ms
依次执行任务,这次ThreadPool表现良好,但也没有看出和创建新线程相比有多大优势。
结论:.NET2.0 ThreadPool的表现也许不符合大多数人对于ThreadPool的期望,慎用!
补充:后来从网上看到资料,确认是.NET2.0 ThreadPool的一个bug,请参考http://www.cnblogs.com/anhr/archive/2008/05/24/ThreadPool_BUG_in_DotNET_2_0_SP1.html,文章提供了一个work around,就是在调用ThreadPool.QueryWorkItem后马上调用Thread.Sleep(1),经过我的测试有效果。
浙公网安备 33010602011771号