2011-09-29 62 views
4

我知道CLR給每個AppDomainThreadPool時間片工作,但我想,如果通過創建像這樣Thread t = new Thread(...);線程是否由線程池管理?

一個新的線程它由CLR或由AppDomin ThreadPool設法知道嗎?

回答

3

當您使用Thread類創建線程時,您可以控制。您可以根據需要創建它們,並且您可以定義它們是否爲background or foreground(使呼叫進程保持活動狀態),您可以設置它們的Priority,然後啓動並停止它們。

隨着ThreadPoolTask(其中使用ThreadPool幕後)你讓ThreadPool類管理線程的創建,並最大限度地提高線程的可重用性,從而節省您創建一個新的線程所需要的時間。需要注意的一點是,與Thread默認值不同,ThreadPool創建的線程不會使調用進程保持活動狀態。

使用ThreadPool的一個巨大優勢是可以讓少量線程處理大量任務。相反,假設池沒有殺死線程(因爲它是爲了重用而設計的),如果你有一堆由ThreadPool創建的線程,但後來項目數量減少,則ThreadPool閒置很多,浪費資源。

6

Thread t = new Thread();將不受ThreadPool的管理。但它是CLR在操作系統線程上提供的一種抽象。 ThreadPool是一個附加的抽象,它有助於重用線程和共享線程資源。

這裏是在.NET上線的優秀資源:http://www.albahari.com/threading/

如果你使用.NET 4.0考慮使用第三方物流。

+0

我使用.NET 4.0 在面試時,我說,一個線程不是由線程池管理和組長說我錯了。現在的問題是我糾正他:) – guyl

+0

真棒鏈接,謝謝! –

1

當您創建新線程時,它們是由線程池管理的而不是

1

如果您手動創建線程,那麼您可以控制其使用壽命,這與線程池無關。

0

以下示例說明如何使用線程池。它首先創建一個ManualResetEvent對象,該對象使程序能夠知道線程池何時完成了所有工作項目的運行。接下來,它試圖向線程池添加一個線程。如果成功,則添加其餘部分(本例中爲四個)。線程池然後將工作項放入可用的線程中。 eventX上的WaitOne方法被調用,這會導致程序的其餘部分等待,直到觸發事件(使用eventX.Set方法)。最後,程序打印線程上的加載(實際執行特定工作項的線程)。

// SimplePool.cs 
// Simple thread pool example 
using System; 
using System.Collections; 
using System.Threading; 

// Useful way to store info that can be passed as a state on a work item 
public class SomeState 
{ 
    public int Cookie; 
    public SomeState(int iCookie) 
    { 
     Cookie = iCookie; 
    } 
} 

public class Alpha 
{ 
    public Hashtable HashCount; 
    public ManualResetEvent eventX; 
    public static int iCount = 0; 
    public static int iMaxCount = 0; 
    public Alpha(int MaxCount) 
    { 
     HashCount = new Hashtable(MaxCount); 
     iMaxCount = MaxCount; 
    } 

    // Beta is the method that will be called when the work item is 
    // serviced on the thread pool. 
    // That means this method will be called when the thread pool has 
    // an available thread for the work item. 
    public void Beta(Object state) 
    { 
     // Write out the hashcode and cookie for the current thread 
     Console.WriteLine(" {0} {1} :", Thread.CurrentThread.GetHashCode(), 
     ((SomeState)state).Cookie); 
     // The lock keyword allows thread-safe modification 
     // of variables accessible across multiple threads. 
     Console.WriteLine(
     "HashCount.Count=={0}, Thread.CurrentThread.GetHashCode()=={1}", 
     HashCount.Count, 
     Thread.CurrentThread.GetHashCode()); 
     lock (HashCount) 
     { 
     if (!HashCount.ContainsKey(Thread.CurrentThread.GetHashCode())) 
      HashCount.Add (Thread.CurrentThread.GetHashCode(), 0); 
     HashCount[Thread.CurrentThread.GetHashCode()] = 
      ((int)HashCount[Thread.CurrentThread.GetHashCode()])+1; 
     } 

     // Do some busy work. 
     // Note: Depending on the speed of your machine, if you 
     // increase this number, the dispersement of the thread 
     // loads should be wider. 
     int iX = 2000; 
     Thread.Sleep(iX); 
     // The Interlocked.Increment method allows thread-safe modification 
     // of variables accessible across multiple threads. 
     Interlocked.Increment(ref iCount); 
     if (iCount == iMaxCount) 
     { 
     Console.WriteLine(); 
     Console.WriteLine("Setting eventX "); 
     eventX.Set(); 
     } 
    } 
} 

public class SimplePool 
{ 
    public static int Main(string[] args) 
    { 
     Console.WriteLine("Thread Pool Sample:"); 
     bool W2K = false; 
     int MaxCount = 10; // Allow a total of 10 threads in the pool 
     // Mark the event as unsignaled. 
     ManualResetEvent eventX = new ManualResetEvent(false); 
     Console.WriteLine("Queuing {0} items to Thread Pool", MaxCount); 
     Alpha oAlpha = new Alpha(MaxCount); // Create the work items. 
     // Make sure the work items have a reference to the signaling event. 
     oAlpha.eventX = eventX; 
     Console.WriteLine("Queue to Thread Pool 0"); 
     try 
     { 
     // Queue the work items, which has the added effect of checking 
     // which OS is running. 
     ThreadPool.QueueUserWorkItem(new WaitCallback(oAlpha.Beta), 
      new SomeState(0)); 
     W2K = true; 
     } 
     catch (NotSupportedException) 
     { 
     Console.WriteLine("These API's may fail when called on a non-Windows 2000 system."); 
     W2K = false; 
     } 
     if (W2K) // If running on an OS which supports the ThreadPool methods. 
     { 
     for (int iItem=1;iItem < MaxCount;iItem++) 
     { 
      // Queue the work items: 
      Console.WriteLine("Queue to Thread Pool {0}", iItem); 
      ThreadPool.QueueUserWorkItem(new WaitCallback(oAlpha.Beta),new SomeState(iItem)); 
     } 
     Console.WriteLine("Waiting for Thread Pool to drain"); 
     // The call to exventX.WaitOne sets the event to wait until 
     // eventX.Set() occurs. 
     // (See oAlpha.Beta). 
     // Wait until event is fired, meaning eventX.Set() was called: 
     eventX.WaitOne(Timeout.Infinite,true); 
     // The WaitOne won't return until the event has been signaled. 
     Console.WriteLine("Thread Pool has been drained (Event fired)"); 
     Console.WriteLine(); 
     Console.WriteLine("Load across threads"); 
     foreach(object o in oAlpha.HashCount.Keys) 
      Console.WriteLine("{0} {1}", o, oAlpha.HashCount[o]); 
     } 
     return 0; 
    } 
} 

出把

Thread Pool Sample: 
Queuing 10 items to Thread Pool 
Queue to Thread Pool 0 
Queue to Thread Pool 1 
... 
... 
Queue to Thread Pool 9 
Waiting for Thread Pool to drain 
98 0 : 
HashCount.Count==0, Thread.CurrentThread.GetHashCode()==98 
100 1 : 
HashCount.Count==1, Thread.CurrentThread.GetHashCode()==100 
98 2 : 
... 
... 
Setting eventX 
Thread Pool has been drained (Event fired) 

Load across threads 
101 2 
100 3 
98 4 
102 1