TreadPool
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的更多相关文章
- Python(八)进程、线程、协程篇
本章内容: 线程(线程锁.threading.Event.queue 队列.生产者消费者模型.自定义线程池) 进程(数据共享.进程池) 协程 线程 Threading用于提供线程相关的操作.线程是应用 ...
- 搞懂 SynchronizationContext(第一部分)【翻译】
SynchronizationContext -MSDN 很让人失望 我不知道为什么,目前在.Net下关于这个类只有很少的资料.MSDN文档也只有很少的关于如何使用SynchronizationCon ...
- JVM 内部运行线程介绍
转(http://club.alibabatech.org/article_detail.htm?articleId=4) JVM 内部运行线程介绍 作者:蒋家佳/觉梦(支付宝开发工程师) 浏览量: ...
- 搞懂 SynchronizationContext
SynchronizationContext -MSDN 很让人失望 我不知道为什么,目前在.Net下关于这个类只有很少的资料.MSDN文档也只有很少的关于如何使用SynchronizationCon ...
- Clr Via C#读书笔记---计算限制的异步操作
线程池基础 1,线程的创建和销毁是一个昂贵的操作,线程调度以及上下文切换耗费时间和内存资源. 2,线程池是一个线程集合,供应你的用程序使用. 3,每个CLR有一个自己的线程池,线程池由CLR控制的所有 ...
- python第十一天-----补:线程池
低版本: #!/usr/bin/env python import threading import time import queue class TreadPool: ""&q ...
- [CLR via C#]26. 计算限制的异步操作
一.CLR线程池基础 前面说过,创建和销毁线程是一个比较昂贵的操作,太多的线程也会浪费内存资源.由于操作系统必须调度可运行的线程并执行上下文切换,所以太多的线程还有损于性能.为了改善这个情况,CLR使 ...
- Ubuntu14.04安装ROOT集群
之前尝试在CentOS7上部署ROOT集群,却发现无论是源码包安装,还是官方提供的二进制包,都缺少了关键的xproofd可执行文件,导致PoD不能运行.没有办法,只能尝试在其他OS上部署,这里我选择了 ...
- 性能分析之-- JAVA Thread Dump 分析综述
性能分析之-- JAVA Thread Dump 分析综述 一.Thread Dump介绍 1.1什么是Thread Dump? Thread Dump是非常有用的诊断Java应用问题的工 ...
随机推荐
- hdu 1006 Tick and Tick
Tick and Tick Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tot ...
- Chrome 浏览器光标定位到地址栏
Windows: Ctrl + L 或 Alt + D Mac: Command + L Linux: Ctrl + L
- RocketMQ之三:RocketMQ集群环境搭建
1.初步理解Producer/Consumer Group 在安装RocketMQ之前我们先来理解Group概念,在RocketMQ中Group是很重要的.通过Group机制,让RocketMQ天然的 ...
- Oracle数据库四种数据完整性约束
Oracle数据库四种数据完整性约束 1.实体完整性 同样的数据不能重复插入(1)采取什么措施保证实体完整性?我们可以给表创建主键约束吗,主键保证了数据的唯一性,主键可以保证同一条记录只能插入一次. ...
- Java面试笔记整理4
一.Java内存溢出的产生原因和解决办法? java.lang.OutOfMemoryError这个错误我相信大部分开发人员都有遇到过,产生该错误的原因大都出于以下原因:JVM内存过小.程序不严密,产 ...
- Ribbon【入门】
公共依赖: <parent> <groupId>org.springframework.boot</groupId> <artifactId>sprin ...
- 正则与re模块
一.正则表达式 在线测试工具 http://tool.chinaz.com/regex/ 1.字符组 在同一个位置可能出现的各种字符组成一个字符组,在正则表达中用[ ]表示 一个正则就是一条匹 ...
- 十一、三星平台framebuffer驱动
和总线设备驱动模型类似,framebuffer分为核心层.驱动层和设备层. 核心层:就是上一章分析的fbmem.c文件 驱动层(控制器层):一般由芯片原厂提供,实现了LCD控制器通用的操作接口和配置接 ...
- PL/SQL Developer的错误提示弹框的文本显示乱码问题
问题:Windows中文环境下,PL/SQL Developer的错误提示弹框文本为乱码,如下: 解决过程:1.使用SELECT * FROM v$nls_parameters;查询得知服务器的字符集 ...
- Linux装好系统之后配置环境
1.配置IP地址vi /etc/sysconfig/network-scripts/ifcfg-eth0 ONBOOT=yes NM_CONTROLLED=yes BOOTPROTO=static D ...