linux c++ 线程池实现
大致实现思路:一共三个类,任务基类:主要用于定义run()接口和一些公共成员以便继承;任务派生类:具体任务实现,继承自任务基类,实现run()接口;线程池类:提供管理线程的功能,主要包括创建线程,监控线程状态(空闲还是忙碌),可以添加任务的任务队列,任务处理结束后销毁线程。
源码如下,一个文件完成,未将定义和实现拆分,但功能简单完整,经过仔细调试,应该无bug了,不过欢迎指正。
/*
Requirement:
Attention: construct data from console is not required, do not implement that logic. Never write code use fgets scanf, getchr, cin or other functions to get input from console.
If you do need data for test, just set the value of variables.
Requirement:
The program creates two thread pools whose names are "key" and "other". Every thread pool includes 3 threads. the relation of thread pool name and thread id the thread id should be printed.
The program can receive strings from stdin. The string which begins with "key" will be delivered to "key" thread pool. Others will be delivered to "other" thread pool.
The thread proc function needs to print thread id and the received strings.
When customer types "exit", the programe will release all the resource and then exit.
*/
#include <vector>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
class Task
{
public:
string m_strTaskDesc;
public:
Task(){}
Task(string taskDesc)
{
this->m_strTaskDesc = taskDesc;
}
virtual int run()= 0;
};
class WorkTask: public Task
{
public:
WorkTask(){}
WorkTask(string taskDesc): Task(taskDesc){}
int run()
{
cout << this->m_strTaskDesc.c_str() << ":" << "be processed "<<"by tid:"<< pthread_self() << endl;
return 0;
}
};
class Threadpool
{
private:
vector<Task*> m_vecTaskList;
int m_iThreadNum;
vector<pthread_t> m_vecIdleThread;
vector<pthread_t> m_vecBusyThread;
pthread_mutex_t m_pthreadMutex;
pthread_cond_t m_pthreadCond;
bool m_bStop;
string m_threadpoolName;
protected:
int moveToIdle(pthread_t tid);
int moveToBusy(pthread_t tid);
int initThreadpool();
bool isExist(vector<pthread_t> &threadList, pthread_t tid);
void removeThread(vector<pthread_t> &threadList, pthread_t tid);
public:
Threadpool(string threadpoolName, int threadNum);
~Threadpool();
void* executeThread();
int addTask(Task *task);
int stopAll();
};
extern "C"
void* startThread(void* arg)
{
Threadpool* tp = (Threadpool*) arg;
tp->executeThread();
return NULL;
}
Threadpool::Threadpool(string threadpoolName, int threadNum)
:m_threadpoolName(threadpoolName), m_iThreadNum(threadNum)
{
pthread_mutex_init(&m_pthreadMutex, NULL);
pthread_cond_init(&m_pthreadCond, NULL);
m_bStop = false;
initThreadpool();
}
Threadpool::~Threadpool()
{
if(!m_bStop)
{
stopAll();
}
if(m_vecTaskList.size() != 0)
{
vector<Task*>::iterator iter = m_vecTaskList.begin();
if(iter != m_vecTaskList.end())
{
m_vecTaskList.erase(iter);
delete *iter;
*iter = NULL;
iter = m_vecTaskList.begin();
}
}
pthread_mutex_destroy(&m_pthreadMutex);
pthread_cond_destroy(&m_pthreadCond);
}
int Threadpool::initThreadpool()
{
for(int i = 0; i < m_iThreadNum; i++)
{
pthread_t tid = 0;
pthread_create(&tid,NULL,startThread,(void*) this);
cout << "PoolName: "<<m_threadpoolName.c_str()<< " Pid: " << tid << endl;
m_vecIdleThread.push_back(tid);
}
return 0;
}
bool Threadpool::isExist(vector<pthread_t> &threadList, pthread_t tid)
{
vector<pthread_t>::iterator iter = threadList.begin();
while(iter != threadList.end())
{
if(tid == *iter)
{
return true;
}
iter++;
}
return false;
}
void Threadpool::removeThread(vector<pthread_t> &threadList, pthread_t tid)
{
vector<pthread_t>::iterator iter = threadList.begin();
while(iter != threadList.end())
{
if(tid == *iter)
{
threadList.erase(iter);
return;
}
iter++;
}
}
int Threadpool::moveToIdle(pthread_t tid)
{
if(isExist(m_vecBusyThread, tid))
removeThread(m_vecBusyThread, tid);
if(!isExist(m_vecIdleThread, tid))
m_vecIdleThread.push_back(tid);
return 0;
}
int Threadpool::moveToBusy(pthread_t tid)
{
if(isExist(m_vecIdleThread, tid))
removeThread(m_vecIdleThread, tid);
if(!isExist(m_vecBusyThread, tid))
m_vecBusyThread.push_back(tid);
return 0;
}
void* Threadpool::executeThread()
{
Task* task = NULL;
while(true)
{
// waiting for condition
pthread_mutex_lock(&m_pthreadMutex);
while(m_vecTaskList.size() == 0 && !m_bStop)
{
pthread_cond_wait(&m_pthreadCond,&m_pthreadMutex);
}
if( m_bStop)
{
pthread_mutex_unlock(&m_pthreadMutex);
pthread_exit(NULL);
}
// get task and process task
vector<Task*>::iterator iter = m_vecTaskList.begin();
if(iter != m_vecTaskList.end())
{
moveToBusy(pthread_self());
task = *iter;
m_vecTaskList.erase(iter);
}
pthread_mutex_unlock(&m_pthreadMutex);
if(task != NULL)
{
task->run();
delete task;
task = NULL;
pthread_mutex_lock(&m_pthreadMutex);
if( m_bStop)
{
pthread_mutex_unlock(&m_pthreadMutex);
pthread_exit(NULL);
}
moveToIdle(pthread_self());
pthread_mutex_unlock(&m_pthreadMutex);
}
}
return (void*)0;
}
int Threadpool::addTask(Task *task)
{
pthread_mutex_lock(&m_pthreadMutex);
this->m_vecTaskList.push_back(task);
pthread_mutex_unlock(&m_pthreadMutex);
pthread_cond_signal(&m_pthreadCond); // send a signal when get a task
return 0;
}
int Threadpool::stopAll()
{
void *result = NULL;
int ret = -1;
m_bStop = true;
pthread_cond_broadcast(&m_pthreadCond);
vector<pthread_t>::iterator idleIter = m_vecIdleThread.begin();
while(idleIter != m_vecIdleThread.end())
{
ret = pthread_join(*idleIter, NULL);
if(ret != 0)
{
cout << "Cannot join with idle thread tid:"<<(unsigned int)(*idleIter)<<" pthread_join() returned " << ret << ": " << strerror(errno) << endl;
}
cout << "Exit idle thread tid:"<<(unsigned int)(*idleIter)<<" pthread_join() returned " << ret << ": " << strerror(errno) << endl;
idleIter++;
pthread_cond_broadcast(&m_pthreadCond);
}
vector<pthread_t>::iterator busyIter = m_vecBusyThread.begin();
while(busyIter != m_vecBusyThread.end())
{
ret = pthread_join(*busyIter,NULL);
if(ret != 0)
{
cout << "Cannot join with busy thread tid:"<<(unsigned int)(*busyIter)<<" pthread_join() returned " << ret << ": " << strerror(errno) << endl;
}
cout << "Exit busy thread tid:"<<(unsigned int)(*busyIter)<<" pthread_join() returned " << ret << ": " << strerror(errno) << endl;
busyIter++;
pthread_cond_broadcast(&m_pthreadCond);
}
return 0;
}
class ProcessTask
{
public:
ProcessTask();
~ProcessTask();
void inputTaskDesc(string taskDesc);
void startProcessTask();
void stopProcessTask();
private:
vector<string> m_vecTaskDesc;
Threadpool *m_pKeyThreadpool;
Threadpool *m_pOtherThreadpool;
};
ProcessTask::ProcessTask()
{
m_pKeyThreadpool = NULL;
m_pOtherThreadpool = NULL;
}
ProcessTask::~ProcessTask()
{
if(m_pKeyThreadpool != NULL)
{
delete m_pKeyThreadpool;
m_pKeyThreadpool = NULL;
}
if(m_pOtherThreadpool != NULL)
{
delete m_pOtherThreadpool;
m_pOtherThreadpool = NULL;
}
}
void ProcessTask::inputTaskDesc(string taskDesc)
{
if(taskDesc.empty())
return;
if(taskDesc.compare(0, 4, "exit") == 0)
{
stopProcessTask();
}
else
{
m_vecTaskDesc.push_back(taskDesc);
}
}
void ProcessTask::startProcessTask()
{
int index = 1;
string tempTastDesc;
m_pKeyThreadpool = new Threadpool("keyThreadpool", 3);
m_pOtherThreadpool = new Threadpool("OtherThreadpool", 3);
vector<string>::iterator iterTaskDesc = m_vecTaskDesc.begin();
while(iterTaskDesc != m_vecTaskDesc.end())
{
tempTastDesc = *iterTaskDesc;
if(tempTastDesc.compare(0, 3, "key") == 0)
{
WorkTask *task = new WorkTask(tempTastDesc.c_str());
m_pKeyThreadpool->addTask(task);
m_vecTaskDesc.erase(iterTaskDesc);
}
else
{
WorkTask *task = new WorkTask(tempTastDesc.c_str());
m_pOtherThreadpool->addTask(task);
m_vecTaskDesc.erase(iterTaskDesc);
}
iterTaskDesc = m_vecTaskDesc.begin();
index++;
}
}
void ProcessTask::stopProcessTask()
{
if(m_pKeyThreadpool != NULL)
{
m_pKeyThreadpool->stopAll();
}
if(m_pOtherThreadpool != NULL)
{
m_pOtherThreadpool->stopAll();
}
}
int main()
{
char taskDesc[256] = {0};
int index = 0;
ProcessTask processTask;
for(index = 0; index < 10; index++)
{
sprintf(taskDesc, "keyTaskDesc%d", index);
processTask.inputTaskDesc(taskDesc);
}
for(index = 0; index < 10; index++)
{
sprintf(taskDesc, "otherTaskDesc%d", index);
processTask.inputTaskDesc(taskDesc);
}
processTask.startProcessTask();
processTask.inputTaskDesc("exit");
return 0;
}
浙公网安备 33010602011771号