Linux 线程池的实现
线程的创建和回收需要消耗一定的资源,如果一个程序中需要频繁的创建和销毁线程,则可以使用线程池的方式来管理线程,减少线程的创建和销毁过程,从而提高系统性能。
创建一个文件命名为cthread.h, 其中代码如下:
#ifndef _CTHREAD_H_
#define _CTHREAD_H_
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<signal.h>
#include<map>
using namespace std;
/*系统函数semop()调用的使用的联合体*/
#ifndef _SEMUN_
#define _SEMUN_
union semun
{
int val; /*value for SETVAL*/ //SETVAL的值
struct semid_ds *buf; /*buffer for IPC_STAT & IPC_SET*/ //IPC_SATA & IPC_SET
unsigned short *array; /*array for GETALL & SETALL*/ //GETALL & SETALL 值
void *__pad; /*buffer for IPC_INFO*/
};
#endif
class CThread;
void *callback(void *agv);
class CThreadPoll;
class CTask
{
public:
virtual void doTask() = 0; //纯虚函数 该类不能实例化
};
class CThread
{
private: //私有成员变量
bool iswait; //线程是否等待的标记
pthread_t thread_id;
pthread_cond_t thread_cond;
pthread_mutex_t thread_mutex;
protected: //私有成员函数
void wait(); /*挂起本线程*/
public:
CThread(); //构造函数
~CThread(); //析构函数
public:
bool start(); /*begin the thread, the thread wait for task*/
virtual void run() = 0; //纯虚函数
void join(); /*等待线程执行结束*/
void notify(); /*唤醒一个线程 */
void thr_exit(); /*退出线程*/
pthread_t getThreadId(); /*获取线程的id*/
};
class CMyThread : public CThread
{
private:
CTask *task; //任务
bool is_exit; //线程退出标记
public:
~CMyThread(); //析构函数
void run();
int setTask(CTask *task){this->task = task; return 0;}; /*设置任务*/
int setIsExit(bool is_exit){this->is_exit = is_exit; return 0; } /*设置线程的退出标记*/
};
/*任务线程 用来执行任务有别于基类 CThread*/
class CTaskThread : public CThread
{
private:
CThreadPoll *poll; //线程池
CTask *task; //任务
bool is_exit; //线程退出标记
int semid; // 信号量id
int sem_num; // 信号量编号
public:
CTaskThread(int semid, int sem_num, CThreadPoll *poll); //构造函数
~CTaskThread(); //析构函数
public:
int setTask(CTask *task); /*设置任务*/
int setIsExit(bool is_exit){this->is_exit = is_exit; return 0;} /*设置线程的退出标记*/
void run(); /*重写基类的run 方法 用来执行任务。没有任务时挂起;有任务时执行任务*/
};
/*线程池类*/
class CThreadPoll
{
private:
CTask *task;
map<pthread_t, CTaskThread*> busyThread; // 忙碌的线程容器
map<pthread_t, CTaskThread*> idleThread; // 空闲的线程容器
int init_num; // 首次创建的线程数
int max_num; // 线程池中线程的上限
int thread_count; // 线程的数量
int max_idle_num; // 线程池中空闲线程的上限
int semid; // 信号量id
int sem_num; // 信号量编号 对poll中的队列操作时使用
public:
CThreadPoll(int semkey, int init_num, int max_num, int max_idle_num); //构造函数
~CThreadPoll(); //析构函数 --释放线程链表种的线程和任务链表中的任务
public:
void start(); // 初始化一批线程并将这一批线程放入空闲线程容器中
void addTask(CTask *task); // 添加一个任务
void run(); // 调度线程执行任务
void removeBusy(pthread_t thread_id); //将线程从忙碌线程列表中移除
void addBusy(pthread_t thread_id, CTaskThread *taskThread);
void removeIdle(pthread_t thread_id); //将线程从空闲任务列表中移除
void addIdle(pthread_t thread_id, CTaskThread *taskThread); // 将线程加入到空闲线程map中
int getIdleSize(); // 获取当前空闲线程的数量
};
#endif
创建一个文件命名为,cthread.cpp,其内容如下:
#include"cthread.h"
/* 创建一个信号量*/
int sem_create(int key, int sem_num)
{
int semid = 0;
semid = semget(key, sem_num, IPC_CREAT|0666);
if(-1 == semid)
{
perror("shmget");
return -1;
}
return 0;
}
/* p操作 */
void sem_p(int semid, int sem_num)
{
struct sembuf sops[1];
memset(sops, 0x0, sizeof(sops));
sops[0].sem_num = sem_num;
sops[0].sem_op = -1;
sops[0].sem_flg = SEM_UNDO;
if(-1 == semop(semid, sops, 1))
{
perror("p semop");
}
}
/*v操作*/
void sem_v(int semid, int sem_num)
{
struct sembuf sops[1];
memset(sops, 0x0, sizeof(sops));
sops[0].sem_num = sem_num;
sops[0].sem_op = 1;
sops[0].sem_flg = SEM_UNDO;
if(-1 == semop(semid, sops, 1 ))
{
perror("v semop");
}
}
/* 信号量的删除*/
void sem_del(int semid)
{
if(-1 == semctl(semid, IPC_RMID, 0))
{
perror("semstl");
}
}
/* 信号量的初始化*/
void sem_init(int semid, int sem_num, int init_val)
{
union semun my_semun = {0};
my_semun.val = init_val;
if(-1 == semctl(semid, sem_num, SETVAL, my_semun))
{
perror("semctl");
}
}
/* 线程的回调函数*/
void *callback(void *agv)
{
((CThread *)agv)->run();
return NULL;
}
/* 构造函数*/
CThread::CThread()
{
pthread_cond_init(&thread_cond, NULL);
pthread_mutex_init(&thread_mutex, NULL);
iswait = false;
}
/* 析构函数 */
CThread::~CThread()
{
this->join();
pthread_cond_destroy(&thread_cond);
pthread_mutex_destroy(&thread_mutex);
}
bool CThread::start()
{
int ret;
ret = pthread_create(&thread_id, NULL, call_bake, this);
if(ret == -1)
{
perror("pthread_create");
}
return (ret == 0);
}
void CThread::notify()
{
if(iswait == true)
{
pthread_cond_signal(&thread_cond);
}
}
void CThread::wait()
{
int ret= pthread_mutex_lock(&thread_mutex);
if(iswait == false)
{
iswait = true;
ret = pthread_cond_wait(&thread_cond, &thread_mutex);
iswait = false;
}
ret = pthread_mutex_unlock(&thread_mutex);
//perror("pthread_cond_unlock");
}
void CThread::join()
{
int ret = pthread_join(thread_id, NULL);
if (0 != ret)
{
perror("pthread_join");
}
}
void CThread::thr_exit()
{
pthread_exit(&thread_id);
}
pthread_t CThread::getThreadId()
{
return this->thread_id;
}
CTaskThread::CTaskThread(int semid, int sem_num, CThreadPoll *poll)
{
this->poll = poll;
this->semid = semid;
this->sem_num = sem_num;
this->is_exit = false;
}
CTaskThread::~CTaskThread()
{
setIsExit(true);
notify();
join();
}
/* 任务线程的run()方法*/
void CTaskThread::run()
{
for(;;)
{
while(NULL == this->task)
{
if(is_exit == true)
{
thr_exit();
}
wait();
}
if(NULL != this->task)
{
#ifdef DEBUG
printf("this thread_id = %d\n", getThreadId());
#endif
task->doTask();
sem_p(semid, sem_num);
poll->removeBusy(getThreadId());
poll->addIdle(getThreadId(), this);
delete this->task;
this->task = NULL;
sem_v(semid, sem_num);
}
}
}
int CTaskThread::setTask(CTask *task)
{
if(NULL == this->task)
{
this->task = task;
}
return 0;
}
void CThreadPoll::start()
{
int i = 0;
CTaskThread *p_thread = NULL;
for(i=0; i<init_num; i++)
{
p_thread = new CTaskThread(semid, sem_num, this);
p_thread->start();
thread_count++;
sem_p(semid, sem_num);
addIdle(p_thread->getThreadId(), p_thread);
sem_v(semid, sem_num);
}
}
CThreadPoll::CThreadPoll(int semkey, int init_num, int max_num, int max_idle_num)
{
this->init_num = init_num;
this->max_num = max_num;
this->max_idle_num = max_idle_num;
this->task = NULL;
thread_count = 0;
semid = sem_create(semkey,1);
if(-1 == semid)
{
// exit(0);
}
sem_num = 0;
sem_init(semid, 0, 1);
}
CThreadPoll::~CThreadPoll()
{
//map<pthread_t, CTaskThread*> busyThread;
//map<pthread_t, CTaskThread*> idleThread;
}
void CThreadPoll::removeBusy(pthread_t thread_id)
{
busyThread.erase(thread_id);
}
void CThreadPoll::addBusy(pthread_t thread_id, CTaskThread *taskThread)
{
busyThread[thread_id] = taskThread;
}
void CThreadPoll::removeIdle(pthread_t thread_id)
{
idleThread.erase(thread_id);
}
void CThreadPoll::addIdle(pthread_t thread_id, CTaskThread *taskThread)
{
idleThread[thread_id] = taskThread;
}
int CThreadPoll::getIdleSize()
{
return (int)(idleThread.size());
}
void CThreadPoll::addTask(CTask *task)
{
this->task = task;
run();
}
// 线程池的run函数
void CThreadPoll::run()
{
map<pthread_t, CTaskThread*>::iterator it;
CTaskThread *p_thread = NULL;
pthread_t thr_id;
while(NULL != task)
{
sem_p(semid, sem_num);
if(idleThread.size() > 0)
{
it = idleThread.begin();
thr_id = (*it).first;
p_thread = (*it).second;
p_thread->setTask(task);
addBusy(thr_id, p_thread);
removeIdle(thr_id);
p_thread->notify();
sem_v(semid, sem_num);
break;
}
else if(thread_count < max_num)
{
p_thread = new CTaskThread(semid, sem_num, this);
p_thread->start();
thread_count++;
p_thread->setTask(task);
addBusy(thr_id, p_thread);
p_thread->notify();
sem_v(semid, sem_num);
break;
}
sem_v(semid, sem_num);
}
{
sem_p(semid, sem_num);
while((int)(idleThread.size()) > max_idle_num)
{
it = idleThread.begin();
thr_id = (*it).first;
p_thread = (*it).second;
removeIdle(thr_id);
delete p_thread;
thread_count--;
}
sem_v(semid, sem_num);
}
}
void CMyThread::run()
{
for(;;)
{
while(NULL == this->task)
{
if(is_exit == true)
{
thr_exit();
}
wait();
}
if(NULL != this->task)
{
#ifdef DEBUG
printf("this thread_id = %d\n", getThreadId());
#endif
task->doTask();
delete this->task;
this->task = NULL;
}
}
}