多线程(线程池:ThreadPool)-C#

Posted 全栈黑科技

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程(线程池:ThreadPool)-C#相关的知识,希望对你有一定的参考价值。

线程池(ThreadPool)

  • 一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量。 例如,线程数一般取cpu数量+2比较合适,线程数过多会导致额外的线程切换开销。

  • 任务调度以执行线程的常见方法是使用同步队列,称作任务队列。池中的线程等待队列中的任务,并把执行完的任务放入完成队列中。

缘由

产生 线程池的历史原因是为了更好的管理线程,而管理线程开销最好的方式如下:

  1. 尽量少的创建线程并且能将线程反复利用(线程池初始化时没有线程,有程序请求线程则创建线程);

  2. 最好不要销毁而是挂起线程达到避免性能损失(线程池创建的线程完成任务后以挂起状态回到线程池中,等待下次请求);

  3. 通过一个技术达到让应用程序一个个执行工作,类似于一个队列(多个应用程序请求线程池,线程池会将各个应用程序排队处理);

  4. 如果某一线程长时间挂起而不工作的话,需要彻底销毁并且释放资源(线程池自动监控长时间不工作的线程,自动销毁);

  5. 如果线程不够用的话能够创建线程,并且用户可以自己定制最大线程创建的数量(当队列过长,线程池里的线程不够用时,线程池不会坐视不理);

于是,机智的微软已经为我们想到了一切,实现了 线程池(ThreadPool

  • CLR线程池并不会在CLR初始化时立即建立线程,而是在应用程序要创建线程来运行任务时,线程池才初始化一个线程。

  • 线程池初始化时是没有线程的,线程池里的。线程的初始化与其他线程一样,但是在完成任务以后,该线程不会自行销毁,而是以挂起的状态返回到线程池。直到应用程序再次向线程池发出请求时,线程池里挂起的线程就会再度激活执行任务。

  • 这样既节省了建立线程所造成的性能损耗,也可以让多个任务反复重用同一线程,从而在应用程序生存期内节约大量开销。

  • 通过CLR线程池所建立的线程总是默认为后台线程,优先级数为 ThreadPriority.Normal

  • 线程池的最大值一般默认为1000、2000。当大于此数目的请求时,将保持排队状态,直到线程池里有线程可用。

工作者线程与I/O线程

CLR线程池分为工作者线程(workerThreads)与I/O线程(completionPortThreads)两种:

  • 工作者线程是主要用作管理CLR内部对象的运作,通常用于计算密集的任务。

  • I/O(Input/Output)线程主要用于与外部系统交互信息,如输入输出,CPU仅需在任务开始的时候,将任务的参数传递给设备,然后启动硬件设备即可。等任务完成的时候,CPU收到一个通知,一般来说是一个硬件的中断信号,此时CPU继续后继的处理工作。在处理过程中,CPU是不必完全参与处理过程的,如果正在运行的线程不交出CPU的控制权,那么线程也只能处于等待状态,即使操作系统将当前的CPU调度给其他线程,此时线程所占用的空间还是被占用,而并没有CPU处理这个线程,可能出现线程资源浪费的问题。如果这是一个网络服务程序,每一个网络连接都使用一个线程管理,可能出现大量线程都在等待网络通信,随着网络连接的不断增加,处于等待状态的线程将会很消耗尽所有的内存资源。可以考虑使用线程池解决这个问题。

.NET Framework的线程池实现

  • 命名空间System.Threading中的类ThreadPool提供一个线程池,该线程池可用于执行任务、发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。

 
   
   
 
  1. public static class ThreadPool


多线程任务执行

将方法排入队列以便执行。 此方法在有线程池线程变得可用时执行。

 
   
   
 
  1. #public delegate void WaitCallback(object state);

  2. #一个委托,无返回值,一个参数

  3. #WaitCallback:一个 System.Threading.WaitCallback,表示要执行的方法。

  4. #如果此方法成功排队,则为 true;如果无法将该工作项排队,则引发 System.OutOfMemoryException。

  5. public static bool QueueUserWorkItem(WaitCallback callBack);

  6. #state:方法所用数据的对象,可以将数据传进去

  7. public static bool QueueUserWorkItem(WaitCallback callBack, object state);

获取处于活动状态的线程池请求的数目

 
   
   
 
  1. #检索可以同时处于活动状态的线程池请求的数目。所有大于此数目的请求将保持排队状态,直到线程池线程变为可用。

  2. #workerThreads:线程池中辅助线程的最大数目。

  3. #completionPortThreads:线程池中异步 I/O 线程的最大数目。

  4. public static void GetMaxThreads(out int workerThreads, out int completionPortThreads);

  5. #检索线程池在新请求预测中维护的空闲线程数。

  6. public static void GetMinThreads(out int workerThreads, out int completionPortThreads);

设置线程池请求的数目

 
   
   
 
  1. #设置可以同时处于活动状态的线程池的请求数目。所有大于此数目的请求将保持排队状态,直到线程池线程变为可用。

  2. #workerThreads:线程池中辅助线程的最大数目。

  3. #completionPortThreads:线程池中异步 I/O 线程的最大数目。

  4. #如果更改成功,则为 true;否则为 false。

  5. public static bool SetMaxThreads(int workerThreads, int completionPortThreads);

  6. #设置线程池在新请求预测中维护的空闲线程数。

  7. public static bool SetMinThreads(int workerThreads, int completionPortThreads);

检索线程池的可用线程数

 
   
   
 
  1. #检索由 System.Threading.ThreadPool.GetMaxThreads(System.Int32@,System.Int32@)

  2. #方法返回的最大线程池线程数和当前活动线程数之间的差值。

  3. #workerThreads:可用辅助线程的数目

  4. #completionPortThreads:可用异步 I/O 线程的数目。

  5. public static void GetAvailableThreads(out int workerThreads, out int completionPortThreads);

实例

 
   
   
 
  1. using System;

  2. using System.Threading;

  3. public class Example

  4. {

  5.    public static void Main()

  6.    {

  7.        // Queue the task.

  8.        ThreadPool.QueueUserWorkItem(ThreadProc);

  9.        Console.WriteLine("Main thread does some work, then sleeps.");

  10.        Thread.Sleep(1000);

  11.        Console.WriteLine("Main thread exits.");

  12.    }

  13.    // This thread procedure performs the task.

  14.    static void ThreadProc(Object stateInfo)

  15.    {

  16.        // No state object was passed to QueueUserWorkItem, so stateInfo is null.

  17.        Console.WriteLine("Hello from the thread pool.");

  18.    }

  19. }


以上是关于多线程(线程池:ThreadPool)-C#的主要内容,如果未能解决你的问题,请参考以下文章

C 语言编程 — 线程池设计与实现

多线程之旅(ThreadPool 线程池)

多线程二:线程池(ThreadPool)

Java多线程:ThreadPool(中)

C++线程池ThreadPool实现解析

多线程Thread,线程池ThreadPool