一.线程池开发框架
我所开发的线程池由以下几部分组成:
1.工作中的线程。也就是线程池中的线程,主要是执行分发来的task。
2.管理线程池的监督线程。这个线程的创建独立于线程池的创建,按照既定的管理方法进行管理线程池中的所有线程,主要任务是监听任务的到来,唤醒线程池中的空闲线程,分发任务;如果任务增多,动态的创建一批线程加入原来的线程池中,进行工作;适当的销毁线程,减少系统开销。
这个线程池的开发涉及了以下几个数据结构、设计模式和软件结构:
1.任务队列。整个框架有两个任务队列,1)等待任务队列(以下简称wait_queue)。2)正在执行中任务队列(以下简称doing_queue)。队列采用先进先出的数据结构。当一个任务来到时,会先被push到wait_queue,监督线程会一直监督wait_queue中的元素,一旦有任务,便会pop wait_queue中的元素,再push到doing_queue中。
2.单例设计模式。线程池的类被设计成单例模式,防止一个程序中多次创建线程池对象,出现紊乱现象,用户只能调用静态方法初始化得到线程池的对象。
3.回调函数。回调函数的设计主要是为了能够把任务接口(也就是需要线程去执行的任务,通常是一个写好的函数方法)提前初始化注册,然后延迟调用。
下图是所用类的的大概结构图:
程序整体结构如下:
二.线程池开发具体实现
1.思路分析。
线程池顾名思义就是同时有数个线程处于待执行状态,编码上的初始化的实现无非就是循环创建指定数量的线程,然后等待任务的到来唤醒空闲线程。以下是ThreadPoll的类:
class ThreadPool
{
private:
pthread_t *_thread; //线程池
pthread_t *_thread_bak; //备用线程池,当任务过多会自动创建
pthread_t taskqueue_thread; //管理线程
int u4sequence;
int wait_time;
int CANCEL_SIGNAL;
bool F_improve_ThrdPoll; //备用线程池创建标志
Mutex *mutex; //互斥锁
CondThread *task_cond; //条件变量
TaskFuncCallback callback; //声明回调函数,即线程所需要执行的函数
int _num_threads; //线程池数量
//构造函数的实现为private属性,禁止用户用构造函数初始化对象。
ThreadPool(int num_threads):_num_threads(num_threads),
F_improve_ThrdPoll(0),
wait_time(0),
u4sequence(0),
CANCEL_SIGNAL(0){
init(); //一些变量的创建
ManagerThreadInit(); //创建管理线程
ThreadPoolInit(num_threads);//初始化线程池
}
public:
LVQueue<TASK_QUEUE_T> task_wait_queue;//创建任务等待队列
LVQueue<TASK_QUEUE_T> task_doing_queue;//创建任务执行队列
~ThreadPool(){
delete(mutex);
delete(task_cond);
delete(_thread);
delete(_thread_bak);
}
//用户通过调用此静态方法得到线程池的对象(单例模式)
static ThreadPool* createThreadPool(int num)
{
static ThreadPool *_pool = new ThreadPool(num);
return _pool;
}
void init(){
_thread = new pthread_t[_num_threads];
mutex = new Mutex();
task_cond = new CondThread();
}
API_RETURN_TYPE_T ThreadPoolInit(int num_thr);//线程池初始化,核心接口
API_RETURN_TYPE_T run(); //线程执行函数
API_RETURN_TYPE_T ManagerThreadInit();//管理线程初始化
API_RETURN_TYPE_T managerThread();线程执行函数
API_RETURN_TYPE_T wakeupThread(TaskFuncCallback p_func);//用户调用此接口唤醒线程执行任务,参数为传入的任务执行函数地址
API_RETURN_TYPE_T AutoComputeOptimumThreadNum(int wait_que_num,int &_u4sequence);//一种自动计算需要增加多少线程到线程池,当任务繁多时会调到。
API_RETURN_TYPE_T ThreadJoin();//所有线程阻塞
API_RETURN_TYPE_T ReleaseSubThreadPool();//释放备用线程池
API_RETURN_TYPE_T DestroyThreadPool();//释放线程池
};
下面是cpp的实现:
//线程池初始化的实现
API_RETURN_TYPE_T ThreadPool::ThreadPoolInit(int num_thr)
{
printf("num = %d.\n",num_thr);
if(num_thr == 0)
{
return API_SUCCESS;
}
//设置创建线程的属性为DETACHED,线程被释放后,资源会被回收。
pthread_attr_t attr;
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
int i = 0;
if(F_improve_ThrdPoll == 1)//备用线程池创建的标志位,初始化线程不会走这边
{
_thread_bak = new pthread_t[num_thr];
for(;i < num_thr;i++)
{
if(RET_OK != pthread_create(&(_thread_bak[i]), &attr, &thread_func, this))
{
return API_FAIL;
}
}
return API_SUCCESS;
}
//create thread pool.
for(;i < num_thr;i++)
{
if(RET_OK != pthread_create(&(_thread[i]), &attr, &thread_func, this))
{
return API_FAIL;
}
}
pthread_attr_destroy (&attr);
return API_SUCCESS;
}
//创建的所有线程都会跑到这个线程函数,最终指向run
void *thread_func(void *arg)
{
ThreadPool *thread = (ThreadPool*)arg;
thread->run();
}
//线程池核心内容
API_RETURN_TYPE_T ThreadPool::run()
{