线程池ThreadPool知识碎片和使用经验速记
ThreadPool(线程池)大概的工作原理是,初始时线程池中创建了一些线程,当应用程序需要使用线程池中的线程进行工作,线程池将会分配一个线程,之后到来的请求,线程池都会尽量使用池中已有的这个线程进行响应,如果请求过多的话,线程池将会按照策略等待或者创建新的线程进行响应直到达到上限。当线程池中的线程处于空闲状态一定时间后(具体多少看环境)线程池池内的空闲线程将会进行自我终结。
1、CLR的一个进程内会维护一个线程池,线程池被该进程内所有应用程序域共享。托管线程池中的线程为后台线程, 即线程的IsBackground属性为true。这意味着在所有的前台线程都已退出后,ThreadPool 线程不会让应用程序保持运行。
2、从.NET4.0开始,进程的线程池的默认大小由虚拟地址空间的大小等多个因素决定,它的默认大小为每个可用处理器250个辅助线程,再加上1000个I/O完成线程。进程可以调用 GetMaxThreads 方法以确定线程的数量。 使用 SetMaxThreads 方法可以更改线程池中的线程数。 每个线程使用默认的堆栈大小并按照默认的优先级运行。
3、线程池分为两类,一类是Work Thread(计算密集型),一类是IO Thread(IO密集型)。IO密集型线程可以在不占用CPU的情况下通过设备驱动程序进行IO操作,比如带BeginXXX和Endxxx方法的文件操作、网络访问等方法。这种带Begin/End的异步操作写法也就是熟知的Asynchronous Programming Model (APM)模式。使用APM模式,调用BeginInvoke却不调用EndInvoke会使得线程资源无法回收引发memory leak,高并发条件下会造成应用程序崩溃。
4、委托的BeginInvoke方法,本质上也是通过线程池完成工作的,所以我们熟知的Func、Action等委托,通过BeginInvoke的方式异步调用方法,必须要写对应的callback,因为调用BeginInvoke却不调用EndInvoke会使得线程资源无法回收。
5、并行开发TPL技术背后离不开ThreadPool,FCL的Task在线程池的基础上进行了优化,并提供了更多更强大且方便的功能,如Task支持线程的取消、完成、失败通知等交互性操作,以及支持线程执行的先后次序。
6、.NET4.5自带的async和await,就是基于.NET4.0里的Task和Parallel的再开发,归根结底是调用Task的语法糖,它们的实现也离不开线程池在背后的工作。
7、在线程池中调用Thread.Sleep方法会导致该线程池中的某工作线程挂起,无法回到池中,当然无法处理其他任务,也就是说这个线程此时只是在休息,不能干其他活。
8、在多线程、异步及并行操作中,异常处理必须非常小心,如果不捕获会导致该线程所属进程崩溃。
参考:
http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx
http://msdn.microsoft.com/en-us/library/hh191443.aspx
http://www.cnblogs.com/yuyijq/category/278984.html
<<CLR via C#>>
作者:Jeff Wong
出处:http://jeffwongishandsome.cnblogs.com/
本文版权归作者和博客园共有,欢迎围观转载。转载时请您务必在文章明显位置给出原文链接,谢谢您的合作。