概述
到目前为止我们使用多线程应用程序的目的是尽可能多地使用计算机处理器资源。所以,看起来我们仅需要为每个独立的任务分配一个不同的线程,并让处理器确定在任何时间它总会处理其中的某一个任务。额,对小系统来说这样做很好。但是当系统越来越复杂时,线程的数量也会越来越多,操作系统将会花费更多时间处理锁分配,理清线程之间的关系,处理程序指令的时间实际上是很少的。为了让我们的程序具备可扩展性,我们将不得不对线程进行一些控制。
对那些生存周期比较短的线程来说,使用线程池来处理任务要比为每个任务都创建一个线程然后顺序地回收它们要高效得多。一个任务,在概念上说,可以是一个单一方法的执行过程或者一系列方法的执行过程。为一个线程预分配一个集合或者一个池来以备未来之需以及能够在一个应用程序中重用的技术称作线程池。
这一章主要对线程池进行详细地介绍,主要覆盖以下主题:
1. 什么是线程池?
2. 为什么需要线程池?
3. 线程池的概念。
4. 线程池中CLR 的角色。
5. 线程池的缺陷以及它们的解决方案。
6. 一个线程池的大小。
7. 探讨.NET ThreadPool 类。
8. 使用C# 语言编写线程池相关应用。
你将发现.NET Framework 中通用语言运行时在线程池技术中起到了很重要的作用。
什么是线程池?
线程池是指在初始化一个多线程应用程序过程中创建一个线程集合,然后在需要执行新的任务时重用这些线程而不是新建一个线程。线程池中线程的数量通常完全取决于可用内存数量和应用程序的需求。然而,增加可用线程数量是可能的。线程池中的每个线程都有被分配一个任务,一旦任务已经完成了,线程回到池子中并等待下一次分配任务。
为什么需要线程池?
基于以下几个原因在多线程应用程序中使用线程是必须的:
1. 线程池改进了一个应用程序的响应时间。由于线程池中的线程已经准备好且等待被分配任务,应用程序可以直接拿来使用而不用新建一个线程。
2. 线程池节省了CLR 为每个短生存周期任务创建一个完整的线程的开销并可以在任务完成后回收资源。
3. 线程池根据当前在系统中运行的进程来优化线程时间片。
4. 线程池允许我们开启多个任务而不用为每个线程设置属性。
5. 线程池允许我们为正在执行的任务的程序参数传递一个包含状态信息的对象引用。
6. 线程池可以用来解决处理一个特定请求最大线程数量限制问题。
线程池的概念
影响一个多线程应用程序的相应时间的几个主要因素之一是为每个任务生成一个线程的时间。
例如,一个Web Server 是一个多线程应用程序,它可以同时对多个客户端请求提供服务。让我们假设有十个客户端同时访问Web Server:
1. 如果服务执行一个客户端对应一个线程的策略,它将为这些客户端生成十个新线程,从创建第一个线程开始到在线程的整个生命周期管理它们都会增加系统开销。也有可能在某个时间计算机的资源耗尽。
2. 相反的,如果服务端使用一个线程池来处理这些请求,那么当每次客户端请求来到后都创建一个线程的时间会节省下来。它可以管理已经创建的线程,如果线程池太忙的话也可以拒绝客户端请求。这是线程池背后的概念。
.NET CLR 为服务请求维护一个线程池。如果我们的应用程序从线程池中请求一个新线程,CLR 将试着从线程池中取出一个。如果线程池是空的,它将生成一个新线程并把它给我们。当我们的代码使用的线程结束以后,线程由.NET 回收并返回给线程池。线程池中线程的数量由当前可用地内存数量决定。
现在回顾一下,影响设计一个多线程应用程序的因素有:
1. 一个应用程序的响应时间。
2. 线程管理资源的分配。
3. 资源共享。
4. 线程同步。
使用线程池的作用:
1.减少在创建和销毁线程上所花的时间以及系统资源的开销
2.如不使用线程池,有可能造成系统创建大量线程而导致消耗完系统内存以及”过度切换”。