Liunx下C++简单线程池实现

版权声明:Dream_dog专属 https://blog.csdn.net/Dog_dream/article/details/87829652

线程池

  线程池就是预先创建好线程等待任务到来,然后接受任务去执行。在一定程度上减少了临时开辟线程的时间,提高程序运行效率。线程池一般需要一个管理线程,任务队列,空闲线程队列,工作线程队列。
管理线程:一般用于监视线程池的工作状态,当任务过多时就会增加线程参加工作,当任务比较少的时候销毁一些空闲线程减少资源销毁。
任务队列:用于存放任务;
空闲线程队列:存放没有任务执行的线程;
工作线程队列:存放处于工作中的线程;
代码如下:
头文件:thread_pool.h

#include <cstdio>
#include <cstdlib>
#include <pthread.h>
#include <signal.h>
#include <assert.h>
#include <cstring>
#include <errno.h>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <unistd.h>
using namespace std;
const int CHECKTIME = 2;
const int PTHREADGAP= 10;
const int DEFAULTNUM= 4;

//任务节点
typedef class Task
{
public:
    Task(){};
    Task(string& taskName): strTaskName(taskName), ptrData(nullptr){};
    virtual ~Task(){};
    virtual int run() = 0;//纯虚函数。
    void setData(void* data);
protected:
    string strTaskName;
    void* ptrData;
}TASK;

class pthreadPool
{
private:	
    
	int  pthreadNum;//线程池大小
	pthread_t adminTid;//管理线程ID
	static bool shutDown;//是否关闭线程池
	static vector<TASK*> taskList;//任务队列
	static vector<pthread_t> pthreadIdle;//空闲线程
	static vector<pthread_t> pthreadBusy;//工作线程
	static pthread_mutex_t pthreadMutex;//线程池的互斥锁
	static pthread_cond_t  pthreadCond;//条件变量
	
protected:
	void createPool();//初始化线程池
	static void* pthreadFun(void *arg);//线程池执行函数
    static void  moveToIdle(pthread_t tid);//添加到空闲队列去
	static void  moveToBusy(pthread_t tid);//添加到工作队列
    static void* pthreadAdmin(void* arg);//管理线程池
	
public:
	pthreadPool(){};
	pthreadPool(int pthreadNum):pthreadNum(pthreadNum)
	{
		printf("I have created %d threads.\n", pthreadNum);
		createPool();
	};
	~pthreadPool(){};
	void addTask(TASK *task);//添加任务节点
	int  stopAll();//关闭所有线程
	int  pthreadIdleSize();//空闲线程的大小
	int  pthreadBusySize();//工作线程的大小
	int  getTaskSize();//任务队列大小
};
实现代码:thread_pool.cpp
#include"thread_pool.h"

void Task::setData(void* data){
    ptrData = data;
}

//静态成员的初始化
vector<TASK*> pthreadPool::taskList;
vector<pthread_t> pthreadPool::pthreadIdle;
vector<pthread_t> pthreadPool::pthreadBusy;
bool pthreadPool::shutDown=false;//初始化线程池的关闭状态
pthread_mutex_t pthreadPool::pthreadMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t pthreadPool::pthreadCond = PTHREAD_COND_INITIALIZER;

void* pthreadPool::pthreadFun(void *arg)
{
	pthread_t tid=pthread_self();//获取当前线程ID
	while(1)
	{
		pthread_mutex_lock(&pthreadMutex);
		while(taskList.size()==0&&!shutDown)
		{
			pthread_cond_wait(&pthreadCond,&pthreadMutex);
		}
		if(shutDown)//如果线程池关闭则退出线程
		{
			pthread_mutex_unlock(&pthreadMutex);
			cout<<"pthread id :"<<tid<<" exit"<<endl;
			pthread_exit(NULL);
		}
		vector<TASK*>* taskList=(vector<TASK*>*)arg;
		vector<TASK*>::iterator iter=taskList->begin();
		while(iter!=taskList->end())
		{
			moveToBusy(tid);//移动到忙碌线程当中去
			break;
		}
		TASK *task=*iter;
		taskList->erase(iter);

		pthread_mutex_unlock(&pthreadMutex);
		printf(" pthread: %lu is runing->  ",tid);
		task->run();
		moveToIdle(tid);//移动到空闲线程当中去
	}
	return NULL;
}

void pthreadPool::createPool()
{
	for(int i=0;i<this->pthreadNum;++i)
	{
		pthread_t tid=0;
		pthread_create(&tid,NULL,pthreadFun,&taskList);//创建空线程
		pthreadIdle.push_back(tid);//将空线程添加到空线程队列
	}
	//pthread_create(&this->adminTid,NULL,pthreadAdmin,this);//创建admin线程
	return ;
}

void pthreadPool::addTask(TASK *task)
{
	pthread_mutex_lock(&pthreadMutex);
	taskList.push_back(task);
	pthread_cond_signal(&pthreadCond);
	pthread_mutex_unlock(&pthreadMutex);
	return ;
}

void pthreadPool::moveToBusy(pthread_t tid)
{
	vector<pthread_t>::iterator iter=pthreadIdle.begin();
	while(iter!=pthreadIdle.end())
	{
		if(*iter==tid){break;}
		++iter;
	}
	pthreadIdle.erase(iter);
	pthreadBusy.push_back(tid);
	return ;
}

void pthreadPool::moveToIdle(pthread_t tid)
{
	vector<pthread_t>::iterator iter=pthreadBusy.begin();
	while(iter!=pthreadIdle.end())
	{
		if(*iter==tid){break;}
		++iter;
	}
	pthreadBusy.erase(iter);
	pthreadIdle.push_back(tid);
	return ;
}

int  pthreadPool::pthreadIdleSize()
{
	return pthreadIdle.size();
}

int  pthreadPool::pthreadBusySize()
{
	return pthreadBusy.size();
}

int pthreadPool::getTaskSize()
{
	return taskList.size();
}

int pthreadPool::stopAll()
{
	if(shutDown) return -1;
	cout<<"stop all threads"<<endl;
	shutDown=true;
	
	pthread_cond_broadcast(&pthreadCond);
	vector<pthread_t>::iterator iter;
	//等待线程退出
	pthread_join(this->adminTid,NULL);
	for(iter=pthreadIdle.begin();iter!=pthreadIdle.end();++iter)
	{
		pthread_join(*iter,NULL);
	}
	for(iter=pthreadBusy.begin();iter!=pthreadBusy.end();++iter)
	{
		pthread_join(*iter,NULL);
	}
	pthread_mutex_destroy(&pthreadMutex);
    pthread_cond_destroy(&pthreadCond);
	return 0;
}	
void* pthreadPool::pthreadAdmin(void* arg)
{
	pthreadPool* tpool=(pthreadPool*)arg;
	while(!shutDown)
	{
		sleep(CHECKTIME);//固定时间检查
		pthread_mutex_lock(&pthreadMutex);
		if(tpool->shutDown)
		{
			cout<<"admin id:"<<pthread_self()<<" exit"<<endl;
			pthread_exit(NULL);
		}
		int taskSize=tpool->getTaskSize();//任务队列大小
		int idleSize=tpool->pthreadIdleSize();//空闲线程大小
		int busySize=tpool->pthreadBusySize();//工作线程大小
		pthread_mutex_unlock(&pthreadMutex);
		cout<<"busy thread size :"<<busySize<<endl;
		cout<<"idle thread size :"<<busySize<<endl;
		cout<<"task size is :"<<taskSize<<endl;
		//如果任务队列大小大于空线程的创建的新线程的大小
		if(taskSize>=PTHREADGAP&&idleSize<=tpool->pthreadNum)
		{

			pthread_mutex_lock(&pthreadMutex);
			for(int i=0;tpool->pthreadIdleSize()<100&&i<PTHREADGAP;++i)
			{
				pthread_t tid=0;
				pthread_create(&tid,NULL,pthreadFun,&taskList);//创建空线程
				pthreadIdle.push_back(tid);//将空线程添加到空线程队列
				cout<<"admin add a new thread"<<endl; 
			}
			pthread_mutex_unlock(&pthreadMutex);
		}
		
		pthread_mutex_lock(&pthreadMutex);
		//销毁多余的线程
		if(tpool->pthreadBusySize()*2<tpool->pthreadIdleSize())
		{	
			int i=0;
			vector<pthread_t>::iterator iter=pthreadIdle.begin();
			while(iter!=pthreadIdle.end()&&i<DEFAULTNUM)
			{
				cout<<*iter<<"is clear"<<endl;
			//	pthread_cancle(*iter);
				iter=pthreadIdle.erase(iter);
				++i;
			}
		}
		pthread_mutex_unlock(&pthreadMutex);
	}
	return NULL;
}
测试代码:test.cpp
#include"thread_pool.h"

class MyCTask: public Task{
public:
    MyCTask() = default;
    ~MyCTask(){};
    int run(){
        printf("%s\n", (char*)ptrData);
        int x = rand()%4 + 1;
        sleep(2);
        return 0;
    }
};
int main(int argc,char*argv[])
{
	MyCTask task;
    char str[] = "hello, world!";
    task.setData((void*) str);
    pthreadPool tpool(10);
	for(int i = 0; i < 100; i++){
        tpool.addTask(&task);
    }
	while(1){
        printf("There are still %d tasks needed to complete...\n", tpool.getTaskSize());
        if(tpool.getTaskSize()== 0){
            if(tpool.stopAll() == -1){
                printf("Thread Pool clear.\n");
                exit(0);
            }
        }

        sleep(10);
        printf("3 seconds later...\n");
    }  
	return 0;
}

makefile:

SRC=$(wildcard *.cpp)
OBJ=$(patsubst %.cpp ,%.o,${SRC})
TARGETS = $(patsubst %.cpp, %,$(SRC))
all=main
${all}:${OBJ}
	g++ -g -o $@ $^ -pthread
.PHONY:
clean:
	rm  -rf *.o ${all} 

猜你喜欢

转载自blog.csdn.net/Dog_dream/article/details/87829652
今日推荐