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. eNSP——RSTP的基础配置

    原理: RSTP把原来的5种状态缩减为3种.根据端口是否转发用户流量和学习MAC地址来划分:如果不转发用户流量也不学习MAC地址,那么端口状态就是Discarding状态;如果不转发用户流量但是学习M ...

  2. rewrite重写基础实列

    nginx 重写 rewrite 基础及实例 nginx rewrite 正则表达式匹配 大小写匹配 ~ 为区分大小写匹配 ~* 为不区分大小写匹配 !~和!~*分别为区分大小写不匹配及不区分大小写不 ...

  3. cocos creator 判断滑动方向

    定义变量 public firstX = null; public firsty = null; 点击 获取坐标 this.viewNode.on(cc.Node.EventType.TOUCH_ST ...

  4. Jenkins+maven+gitlab自动化部署之基础环境部署(一)

    从一个二线城市,来到上海,刚入职,老大就给任务,为了减少开发打包部署时间,需要搭建一套自动化部署环境.接到任务后,赶紧上网查找资料,以及了解jenkins作用等等,用了一周时间,了解了个大概,由于都是 ...

  5. Java基础---Java方法

    基本方法的定义: public static void 方法名称() { 方法体 } 方法名称的命名规则和变量一样,使用小驼峰. 方法体:也就是大括号当中可以包含任意条语句. 注意事项: 1. 方法定 ...

  6. zcat +文件名.gz | grep "查找内容"

    linux  gz查看 zcat +文件名.gz | grep "查找内容" 解压 rar x xxxx.rar

  7. 关于OI中的各种数学

    学到后面数学越来越多了,感觉好难啊,开个博客专门记录一下数学相关的东西 因为反正也没人看,所以主要还是给自己看的 一些符号: 数论函数的卷积:$\ast$,$ h = f \ast g$ 则 $h(n ...

  8. 笔记: ASP.NET Core视图组件

    视图组件 asp.net core mvc 提供了部分视图的新替代品:视图组件. 视图组件与分布视图的主要区别在于视图组件与控制器不相关.可使用在独立于单个控制器的场景,如:菜单导航.侧边栏.分页栏等 ...

  9. C#四种深拷贝方法(转载)

    原文地址:https://www.cnblogs.com/profession/p/6222489.html //四种深拷贝方法 public static T DeepCopyByReflect&l ...

  10. JVM内存结构划分

    JVM内存结构划分 JVM内存结构划分 数据区域划分 程序计数器 虚拟机栈 本地方法栈 堆 方法区 运行时常量池 StringTable 直接内存 创建新对象说明 对象的创建 对象的内存布局 对象头 ...