天天看點

抓蟲系列(四) 不要輕視web程式中常用的三個"池" 之線程池

前篇回顧:上篇講了資料庫連接配接池的問題,其實關于是否是活動連接配接還是有很大問題可以挖掘的。這個有空蟲子再和大家交流了

本篇談下線程池的相關問題,希望各位看官留個爪印,應用程式池和資料庫連接配接池可能大部分程式員不需要關心那個,不過線程池可所謂是重頭戲了。

先把蟲子的觀點放上: 個人表示排斥在項目中使用ThreadPool這個類,至于.net中關聯到ThreadPool的資源我們暫且不做讨論。如果需要操作線程池可以使用第三方例如SmartThreadPool或者自己按照自己的項目需求開發一個。

線程池的相關概念我就不多說了,同樣這裡我隻介紹下。線程池中容易被忽視的問題。

一. 相對池外線程,池内線程操作的性能極差!

<a href="http://blog.51cto.com/dubing/712451#">?</a>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

<code>ManualResetEvent[] MR = </code><code>new</code> <code>ManualResetEvent[10];</code>

<code>           </code><code>for</code> <code>(</code><code>int</code> <code>i = 0; i &lt; 10; i++)</code>

<code>           </code><code>{</code>

<code>               </code><code>MR[i] = </code><code>new</code> <code>ManualResetEvent(</code><code>false</code><code>);</code>

<code>           </code><code>}</code>

<code>           </code><code>int</code> <code>a, b;</code>

<code>           </code><code>ThreadPool.GetMaxThreads(</code><code>out</code> <code>a, </code><code>out</code> <code>b);</code>

<code>           </code><code>Console.WriteLine(</code><code>string</code><code>.Format(</code><code>"(輔助線程的最大數目{0}  I/O線程的最大數目{1})    初始狀态"</code><code>, a, b));</code>

<code>           </code><code>ThreadPool.GetAvailableThreads(</code><code>out</code> <code>a, </code><code>out</code> <code>b);</code>

<code>           </code><code>Console.WriteLine(</code><code>string</code><code>.Format(</code><code>"(可用輔助線程的最大數目{0}  可用I/O線程的最大數目{1})    初始狀态"</code><code>, a, b));</code>

<code>       </code> 

<code>           </code><code>Stopwatch sw = Stopwatch.StartNew();</code>

<code>             </code> 

<code>               </code><code>new</code> <code>Thread((qq) =&gt;</code>

<code>               </code><code>{</code>

<code>                   </code><code>Console.WriteLine(</code><code>"這是個線程池外的線程"</code><code>+qq.ToString());</code>

<code>                   </code><code>MR[(</code><code>int</code><code>)qq].Set();</code>

<code>                   </code><code>Thread.Sleep(5000);</code>

<code>               </code><code>}) { }.Start(i);</code>

<code>           </code><code>WaitHandle.WaitAll(MR);</code>

<code>           </code><code>Console.WriteLine(</code><code>"生成池外10個線程 共耗時"</code> <code>+ sw.ElapsedMilliseconds);</code>

<code>           </code><code>foreach</code> <code>(ManualResetEvent me </code><code>in</code> <code>MR)</code>

<code>               </code><code>me.Reset();</code>

<code>           </code><code>Thread.Sleep(500);</code>

<code>           </code><code>Console.WriteLine(</code><code>string</code><code>.Format(</code><code>"(可用輔助線程的最大數目{0}  可用I/O線程的最大數目{1})    線程池外啟動線程後"</code><code>, a, b));</code>

<code>           </code><code>sw = Stopwatch.StartNew();</code>

<code>           </code><code>ThreadPool.QueueUserWorkItem(qq =&gt;</code>

<code>               </code><code>{                 </code>

<code>                   </code><code>Console.WriteLine(</code><code>"這是個線程池内的線程"</code> <code>+ qq.ToString());</code>

<code>                   </code><code>Thread.Sleep(20000);</code>

<code>                   </code> 

<code>               </code><code>},i);</code>

<code>           </code><code>Console.WriteLine(</code><code>"生成池内10個線程 共耗時"</code> <code>+ sw.ElapsedMilliseconds);</code>

<code>           </code><code>Thread.Sleep(6000);</code>

<code>           </code><code>Console.WriteLine(</code><code>string</code><code>.Format(</code><code>"(可用輔助線程的最大數目{0}  可用I/O線程的最大數目{1})    線程池内啟動線程後"</code><code>, a, b));</code>

在初始狀态後 生成線程的效率存在百倍的差距!!!不過線程池既然是池的作用那麼在程式運作中應該會好很多。

二。線程池内的線程隻能是背景線程。

三。不能為線程設定優先級。在高精度的項目中線程池不适用。

四。所支援的Callback不能有傳回值。WaitCallback隻能帶一個object類型的參數,沒有任何傳回值。

五。容易被幹擾,同時容易破壞項目的應用環境。舉些例子

<code>static</code> <code>void</code> <code>Main(</code><code>string</code><code>[] args)</code>

<code>        </code><code>{                   </code>

<code>            </code><code>//哪些函數會影響線程池</code>

<code>            </code><code>int</code> <code>a, b;</code>

<code>            </code><code>Timer timer = </code><code>new</code> <code>Timer((qq) =&gt;</code>

<code>            </code><code>{           </code>

<code>                </code><code>Console.WriteLine(</code><code>"這是一個timer"</code><code>);</code>

<code>                </code><code>Thread.Sleep(2000);</code>

<code>            </code><code>}, </code><code>null</code><code>, 2000, 1000);</code>

<code>           </code> 

<code>            </code><code>ThreadPool.GetAvailableThreads(</code><code>out</code> <code>a, </code><code>out</code> <code>b);</code>

<code>            </code><code>Console.WriteLine(</code><code>string</code><code>.Format(</code><code>"(可用輔助線程的最大數目{0}  可用I/O線程的最大數目{1})    Timer啟動後"</code><code>, a, b));</code>

<code>            </code><code>timer.Dispose();</code>

<code>            </code><code>timer = </code><code>new</code> <code>Timer((qq) =&gt;</code>

<code>            </code><code>{         </code>

<code>                </code><code>ThreadPool.GetAvailableThreads(</code><code>out</code> <code>a, </code><code>out</code> <code>b);</code>

<code>                </code><code>Console.WriteLine(</code><code>string</code><code>.Format(</code><code>"(可用輔助線程的最大數目{0}/可用I/O線程的最大數目{1}) Timer資源占用ing"</code><code>, a, b));</code>

<code>            </code><code>var</code> <code>act = </code><code>new</code> <code>Action(testmethod);</code>

<code>            </code><code>var</code> <code>qqt = act.BeginInvoke(CallbackMethod, act);</code>

<code>            </code><code>Console.ReadLine();</code>

<code>        </code><code>}</code>

<code>        </code><code>static</code> <code>void</code> <code>CallbackMethod(IAsyncResult ar)</code>

<code>        </code><code>{</code>

<code>            </code><code>var</code> <code>caller = (Action)ar.AsyncState;</code>

<code>            </code><code>caller.EndInvoke(ar);</code>

<code>            </code><code>Console.WriteLine(</code><code>"Action回調結束"</code><code>);</code>

<code> </code> 

<code>        </code><code>static</code> <code>void</code> <code>testmethod()</code>

<code>            </code><code>Console.WriteLine(</code><code>"Action開始"</code><code>);</code>

<code>            </code><code>Console.WriteLine(</code><code>string</code><code>.Format(</code><code>"(可用輔助線程的最大數目{0}  可用I/O線程的最大數目{1})    Action啟動ing"</code><code>, a, b));</code>

<code>            </code><code>Thread.Sleep(2000);</code>

<code>        </code> 

至于還有哪些,大家可以各自讨論,或者提出反對的意見。

本文轉自 熬夜的蟲子  51CTO部落格,原文連結:http://blog.51cto.com/dubing/712451