日期:2014-05-17  浏览次数:20732 次

Windows下一个比较完美的线程池实现

1.  前言

线程池不是一个新鲜的东西,网上能找到很多原理、实现,甚至很多库都提供了实现,比如微软的 ATL::CThreadPool, Vista后提供的CreateThreadpoolWork, boost 中提供的 thread_pool, CSDN、CodeProject 等网站上很多人已经实现的类。但这些库往往只支持启动任务,而不能很好地停止任务(相信很多人都会和我一样有这个需求),于是我在FTL中写了一个个人认为还比较完美的线程池。

2.  功能

本线程池提供了如下功能:

1.       能根据任务个数和当前线程的多少在最小/最大线程个数之间自动调整(Vista后的系统有 SetThreadpoolThreadMaximum 等函数有类似功能);

2.      能方便的对任一任务进行取消操作,无论该任务是等待运行状态还是正在运行状态都支持(相比较而言,WaitForThreadpoolWorkCallbacks 函数只能取消尚未运行的任务);

3.      能对整个线程池进行安全的暂停、继续、停止处理

4.      支持回调方式的反馈通知

5.      使用模版方式实现,能方便的进行参数传递

6.      在加入任务时可以设置优先级(目前尚不支持动态调整)

7.      使用的是微软的基本API,能支持WinXP、Vista、Win7等各种操作系统(CreateThreadpoolWork 等只能在Vista后才能使用)

3.  UML图示和简单说明

其UML图比较简单,主要的只有三个类:

CFThreadPool – 线程池的管理类,负责整个线程池的管理工作,直接使用即可。

CFJobBase – Job的基类,如果想实现自己的Job,必须从这个类继承,并实现其中的Run/ OnCancelJob 等函数。

IFThreadPoolCallBack– 可选的回调实现,可以通知调用段 Job 的启动、停止、取消、进度通知、错误等各种状态的改变。

4.  实现说明

以下部分简单介绍了一些比较重要的代码实现,具体请参见示例代码和其中的注释部分。

4.1.     Job容器

本线程池类中有两种Job的容器,分别是等待运行的Jobs和当前正在运行的Jobs。因为有不同的需求,其定义分别如下(两种容器类型的选择,其理由已经写得比较详细,大家自行分析即可)

     //! 保存等待Job的信息,由于有优先级的问题,而且从最前面开始取任务,因此保存成set

//! 保证优先级高、JobIndex小(同优先级时FIFO) 的Job在最前面

     typedeftypenameUnreferenceLess<CFJobBase<T>* >JobBaseUnreferenceLess;

     typedefstd::set<CFJobBase<T>*,JobBaseUnreferenceLess > WaitingJobContainer;

     WaitingJobContainer        m_WaitingJobs;    //!等待运行的Job

 

     //! 保存运行Job的信息,由于会频繁加入、删除,且需要按照JobIndex查找删除,因此保存成map

     typedefstd::map<LONG,CFJobBase<T>* >   DoingJobContainer;

     DoingJobContainer      m_DoingJobs//! 正在运行的Job

 

4.2.     Job优先级

代码中通过operator < 方法比较CFJobBase<T>::m_nJobPriority