Linux 线程池的实现

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;			
  	}
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

w517565244live

您的支持是我坚持创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值