簡體   English   中英

線程是否由線程池管理?

[英]Is Thread managed by the thread pool?

我知道CLR給每個AppDomain ThreadPool時間片工作,但我想知道是否通過創建一個新的線程,如此Thread t = new Thread(...);

它是由CLR還是AppDomin ThreadPool

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

以下是.NET中線程的優秀資源: http//www.albahari.com/threading/

如果您使用的是.NET 4.0,請考慮使用TPL。

使用Thread類創建線程時, 可以控制。 您可以根據需要創建它們,並定義它們是后台還是前景 (使調用進程保持活動狀態),設置Priority ,啟動和停止它們。

使用ThreadPoolTask (在幕后使用ThreadPool ),您可以讓ThreadPool類管理線程的創建,並最大化線程的可重用性,從而節省創建新線程所需的時間。 需要注意的一點是,與Thread默認值不同, ThreadPool創建的ThreadPool不會使調用進程保持活動狀態。

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

創建新線程時,它們不受線程池管理。

如果手動創建線程然后控制其生命周期,則它獨立於線程池。

以下示例顯示如何使用線程池。 它首先創建一個ManualResetEvent對象,該對象使程序能夠知道線程池何時完成了所有工作項的運行。 接下來,它嘗試將一個線程添加到線程池。 如果成功,則添加其余部分(本例中為4個)。 然后,線程池將工作項放入可用線程中。 調用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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM