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