ThreadPool概述

提供一个线程池,该线程池可用于执行任务、发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。

创建线程需要时间。如果有不同的小任务要完成,就可以事先创建许多线程/在应完成这些任务时发出请求。不需要自己创建这样一个列表。该列表由ThreadPool类托管。

这个类会在需要时增减池中线程的线程数,直到最大的线程数。池中的最大线程数是可配置的。在双核CPU中,默认设置为1023 个工作线程和1000个I/O线程。也可以指定在创建线程池时应立即启动的最小线程数,以及线程池 中可用的最大线程数。

如果有更多的作业要处理,线程池中线程的个数也达到了极限,最新的作业就要排队,且必须等待线程完成其任务。

线程池使用起来很简单,但它有一些限制:

  • 线程池中的所有线程都是后台线程。如果进程的所有前台线程都结束了,所有的后台线程 就会停止。不能把入池的线程改为前台线程。

  • 不能给入池的线程设置优先级或名称。
  • 对于COM对象,入池的所有线程都是多线程单元(multithreaded apartment, MTA)线程。许 多COM对象都需要单线程单元(single-threaded apartment, MTA)线程。
  • 入池的线程只能用于时间较短的任务。如果线程要一直运行(如Word的拼写检杳器线程), 就应使用Thread类创建一个线程.

使用线程池线程的操作的情况包括:

  • 当您创建Task或Task<TResult>对象以异步方式执行某项任务,默认情况下任务调度在线程池线程上运行的。
  • 异步计时器使用线程池。 线程池线程从System.Threading.Timer类执行回调,和从System.Timers.Timer类引发事件。
  • 当使用已注册的等待句柄时,系统线程监视等待句柄的状态。 等待操作完成后,从线程池的工作线程将执行相应的回调函数。
  • 当您调用QueueUserWorkItem方法进行排队,以在线程池线程上执行的方法。 为此,可将该方法传递WaitCallback委托。

方法

  • GetAvailableThreads(Int32, Int32)   
    检索由 GetMaxThreads(Int32, Int32) 方法返回的最大线程池线程数和当前活动线程数之间的差值。
  • GetMaxThreads(Int32, Int32)   
    检索可以同时处于活动状态的线程池请求的数目。 所有大于此数目的请求将保持排队状态,直到线程池线程变为可用。
  • SetMaxThreads(Int32, Int32)   
    设置可以同时处于活动状态的线程池的请求数目。 所有大于此数目的请求将保持排队状态,直到线程池线程变为可用。
  • GetMinThreads(Int32, Int32)   
    发出新的请求时,在切换到管理线程创建和销毁的算法之前检索线程池按需创建的线程的最小数量。
  • SetMinThreads(Int32, Int32)   
    发出新的请求时,在切换到管理线程创建和销毁的算法之前设置线程池按需创建的线程的最小数量。
  • QueueUserWorkItem(WaitCallback, Object)   
    将方法排入队列以便执行,并指定包含该方法所用数据的对象。 此方法在有线程池线程变得可用时执行。
  • RegisterWaitForSingleObject(WaitHandle, WaitOrTimerCallback, Object, Int32, Boolean)   
    注册一个等待 WaitHandle 的委托,并指定一个 32 位有符号整数来表示超时值(以毫秒为单位)。

获取线程数方法

int i = 0;
int j = 0;
//前面是辅助(也就是所谓的工作者)线程,后面是I/O线程
ThreadPool.GetMaxThreads(out i, out j);
Console.WriteLine(i.ToString() + " " + j.ToString()); //默认都是1000 //获取空闲线程,由于现在没有使用异步线程,所以为空
ThreadPool.GetAvailableThreads(out i, out j);
Console.WriteLine(i.ToString() + " " + j.ToString()); //默认都是1000

QueueUserWorkItem(WaitCallback, Object)

将方法排入队列以便执行,并指定包含该方法所用数据的对象。 此方法在有线程池线程变得可用时执行。

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

实例:

static void Main(string[] args)
{
Person p = new Person(1, "刘备");
//启动工作者线程
ThreadPool.QueueUserWorkItem(new WaitCallback(RunWorkerThread), p);
} static void RunWorkerThread(object obj)
{
Thread.Sleep(200);
Console.WriteLine("线程池线程开始!");
Person p = obj as Person;
Console.WriteLine(p.Name);
} public class Person
{
public Person(int id, string name) { Id = id; Name = name; }
public int Id { get; set; }
public string Name { get; set; }
}

RegisterWaitForSingleObject 注册等待句柄

注册一个等待 WaitHandle 的委托,并指定一个数来表示超时值(以毫秒为单位)。

将指定的方法排队到线程池,当超时或者等待委托接收到信号时,辅助线程将执行此方法,即主线程控制辅助线程什么时候开始执行。

public static System.Threading.RegisteredWaitHandle RegisterWaitForSingleObject (System.Threading.WaitHandle waitObject, System.Threading.WaitOrTimerCallback callBack, object state, int millisecondsTimeOutInterval, bool executeOnlyOnce);

参数

  • waitObject
    要注册的 WaitHandle。 使用 WaitHandle 而非 Mutex。
  • callBack
    向 waitObject 参数发出信号时调用的 WaitOrTimerCallback 委托。
  • state
    传递给委托的对象。
  • millisecondsTimeOutInterval
    以毫秒为单位的超时。 如果 millisecondsTimeOutInterval 参数为 0(零),函数将测试对象的状态并立即返回。 如果 millisecondsTimeOutInterval 为 -1,则函数的超时间隔永远不过期。
    表示间隔几秒执行回调方法,指当刚加入线程后,它是需要过了几秒后才会第一次执行回调方法。如果使用了wait.Set()方法使用立即执行回调函数而不需要等待。
  • executeOnlyOnce
    如果为 true,表示在调用了委托后,线程将不再在 waitObject 参数上等待;如果为 false,表示每次完成等待操作后都重置计时器,直到注销等待。

返回

  • RegisteredWaitHandle
    封装本机句柄的 RegisteredWaitHandle。

// TaskInfo contains data that will be passed to the callback method.
public class TaskInfo
{
public RegisteredWaitHandle Handle = null;
public string OtherInfo = "default";
} public static void Main(string[] args)
{
// 主线程使用AutoResetEvent来给已注册的等待句柄发信号, 此等待句柄执行回调方法
AutoResetEvent ev = new AutoResetEvent(false); TaskInfo ti = new TaskInfo();
ti.OtherInfo = "First task";
// The TaskInfo for the task includes the registered wait handle returned by RegisterWaitForSingleObject. This
// allows the wait to be terminated when the object has been signaled once (see WaitProc).
ti.Handle = ThreadPool.RegisterWaitForSingleObject(
ev,
new WaitOrTimerCallback(WaitProc),
ti,
1000,
false
); // 主线程等待三秒,为了演示队列中的线程超时,然后发信号.
Thread.Sleep(3100);
Console.WriteLine("Main thread signals.");
ev.Set();//发信号 // The main thread sleeps, which should give the callback method time to execute. If you comment out this line, the program usually ends before the ThreadPool thread can execute.
Thread.Sleep(1000);
// If you start a thread yourself, you can wait for it to end by calling Thread.Join. This option is not available with thread pool threads.
} //The callback method executes when the registered wait times out,
//or when the WaitHandle (in this case AutoResetEvent) is signaled.
//WaitProc unregisters the WaitHandle the first time the event is signaled.
public static void WaitProc(object state, bool timedOut)
{
TaskInfo ti = (TaskInfo)state; string cause = "TIMED OUT";
if (!timedOut) //如果Timeout为false,表示接收到的信号后执行的
{
cause = "SIGNALED";
//如果回调方法执行的话是因为WaitHandle触发信号的话,则用反注册等待句柄来取消回调方法将来的执行。
if (ti.Handle != null)
ti.Handle.Unregister(null);//
} Console.WriteLine("WaitProc( {0} ) executes on thread {1}; cause = {2}.",
ti.OtherInfo, Thread.CurrentThread.GetHashCode().ToString(), cause);//超时后执行的
}

结果如下:

WaitProc( First task ) executes on thread 7; cause = TIMED OUT.
WaitProc( First task ) executes on thread 7; cause = TIMED OUT.
WaitProc( First task ) executes on thread 7; cause = TIMED OUT.
Main thread signals.
WaitProc( First task ) executes on thread 7; cause = SIGNALED.

TreadPool的更多相关文章

  1. Python(八)进程、线程、协程篇

    本章内容: 线程(线程锁.threading.Event.queue 队列.生产者消费者模型.自定义线程池) 进程(数据共享.进程池) 协程 线程 Threading用于提供线程相关的操作.线程是应用 ...

  2. 搞懂 SynchronizationContext(第一部分)【翻译】

    SynchronizationContext -MSDN 很让人失望 我不知道为什么,目前在.Net下关于这个类只有很少的资料.MSDN文档也只有很少的关于如何使用SynchronizationCon ...

  3. JVM 内部运行线程介绍

    转(http://club.alibabatech.org/article_detail.htm?articleId=4) JVM 内部运行线程介绍 作者:蒋家佳/觉梦(支付宝开发工程师) 浏览量: ...

  4. 搞懂 SynchronizationContext

    SynchronizationContext -MSDN 很让人失望 我不知道为什么,目前在.Net下关于这个类只有很少的资料.MSDN文档也只有很少的关于如何使用SynchronizationCon ...

  5. Clr Via C#读书笔记---计算限制的异步操作

    线程池基础 1,线程的创建和销毁是一个昂贵的操作,线程调度以及上下文切换耗费时间和内存资源. 2,线程池是一个线程集合,供应你的用程序使用. 3,每个CLR有一个自己的线程池,线程池由CLR控制的所有 ...

  6. python第十一天-----补:线程池

    低版本: #!/usr/bin/env python import threading import time import queue class TreadPool: ""&q ...

  7. [CLR via C#]26. 计算限制的异步操作

    一.CLR线程池基础 前面说过,创建和销毁线程是一个比较昂贵的操作,太多的线程也会浪费内存资源.由于操作系统必须调度可运行的线程并执行上下文切换,所以太多的线程还有损于性能.为了改善这个情况,CLR使 ...

  8. Ubuntu14.04安装ROOT集群

    之前尝试在CentOS7上部署ROOT集群,却发现无论是源码包安装,还是官方提供的二进制包,都缺少了关键的xproofd可执行文件,导致PoD不能运行.没有办法,只能尝试在其他OS上部署,这里我选择了 ...

  9. 性能分析之-- JAVA Thread Dump 分析综述

    性能分析之-- JAVA Thread Dump 分析综述       一.Thread Dump介绍 1.1什么是Thread Dump? Thread Dump是非常有用的诊断Java应用问题的工 ...

随机推荐

  1. layer弹出层,结合art-template实现弹出编辑

    模板 <!-- 模板 --> <script id="render-tpl" type="text/html"> <div cla ...

  2. java源码 -- HashSet

    概述 HashSet是基于HashMap来实现的, 底层采用HashMap的key来保存数据, 借此实现元素不重复, 因此HashSet的实现比较简单, 基本上的都是直接调用底层HashMap的相关方 ...

  3. 解决maven项目无法读取src/main/java目录下面的配置文件问题

    我们在用Mybatis去操作底层数据库的时候,需要用到xml配置文件,一般我们是把配置文件和dao放置在同一层目录. 但是在用idea操作maven项目的时候,我们可能会遇到无法读取到dao对应的ma ...

  4. k8s集群监控 cadvisor/exporter+prometheus+grafana

    ### k8s监控处理 ### 1.cadvisor/exporter+prometheus+grafana 安装#### 1.1 配置nfs安装```shellubuntu: nfs 服务器 apt ...

  5. [二叉树算法]让树所有叶子节点连成一个单链表,让rchild作为 next指针

    //让树所有叶子节点连成一个单链表,让rchild作为 next指针 LNode *head=null,*pre=null;//全局变量 LNode *InOrder(BTNode *T){ if(T ...

  6. jq勾选

    1.取消勾选 $("box").attr("checked", false); 2.勾选 $("kbox").attr("chec ...

  7. 恺撒密码 I

    恺撒密码 I ‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‭ ...

  8. moment.js(日期处理类库)的使用

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. PHP函数问题

    有时候,运行nginx和PHP CGI(PHP FPM)web服务的Linux服务器,突然系统负载上升,用top命令查看,很多phpcgi进程的CPU利用率接近100%后来通过跟踪发现,这种情况与PH ...

  10. react请求接口数据是在componentDidMount 还是componentWillMount周期好

    如果你要获取外部数据并加载到组件上,只能在组件"已经"挂载到真实的网页上才能作这事情,其它情况你是加载不到组件的.componentDidMount方法中的代码,是在组件已经完全挂 ...