C++11的多线程并发编程(六)–线程池
这篇主要记录线程池的写法,线程池就是有一堆已经创建好了的线程,初始都处于空闲等待状态,当有任务需要处理是,就从线程池中取一个空闲等待的线程来处理该仍无,等任务处理完毕后,就再次把线程放回池中,其实就是设置线程的状态,当线程池里的都处于忙碌状态,那么就根据需要创建一个新的线程,或者等待。
- threadPool.h
头文件主要用来写任务类,定义任务类成员,以及成员函数,以及线程池管理类,定义线程数目,任务列表,线程入口函数,以及线程切换状态函数。
#ifndef _THREAD_POOL_H
#define _THREAD_POOL_H
#include <vector>
#include <iostream>
#include <string>
#include <pthread.h>
using namespace std;
//this class is for task excuting
class CTask
{
protected:
string strTaskname;
void *ptrData;
public:
CTask() = default;
CTask(string &taskName): strTaskname(taskName), ptrData(NULL){}
virtual int Run() = 0;
void setData(void* data);
virtual ~CTask(){}
};
class CThreadPool
{
private:
static vector<CTask*> vecTasklist;
static bool shutdown;
int threadNum;
pthread_t *pthread_id;
static pthread_mutex_t pthreadMutex;
static pthread_cond_t pthreadCond;
protected:
static void *ThreadFunc(void *threadData);
static int MoveToIdle(pthread_t tid);
static int MoveToBusy(pthread_t tid);
int Create();
public:
CThreadPool(int threadNum);
int AddTask(CTask *task);
int StopAll();
int getTaskSize();
};
#endif
2.threadPool.cpp
主要用来设置成员初始化,定义线程成员函数,添加任务函数,创建线程函数,这里用的都是linux提供的POXIS的线程API,学习学习。
#include "threadPool.h"
#include <cstdio>
#include <iostream>
void CTask::setData(void *data)
{
ptrData = data;
}
vector<CTask*> CThreadPool::vecTasklist;
bool CThreadPool::shutdown = false;
pthread_mutex_t CThreadPool::pthreadMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t CThreadPool::pthreadCond = PTHREAD_COND_INITIALIZER;
CThreadPool::CThreadPool(int threadNums)
{
this->threadNum = threadNums;
cout << "I will create "<< threadNums << endl;
Create();
}
void *CThreadPool::ThreadFunc(void *threadData)
{
pthread_t tid = pthread_self();
while(1)
{
pthread_mutex_lock(&pthreadMutex);
while(vecTasklist.size() == 0 && !shutdown)
pthread_cond_wait(&pthreadCond, &pthreadMutex);
if(shutdown)
{
pthread_mutex_unlock(&pthreadMutex);
printf("[tid: %lu]\texit\n", pthread_self());
pthread_exit(NULL);
}
printf("[tid: %lu]\trun: ", tid);
vector<CTask*>::iterator iter = vecTasklist.begin();
CTask *task = *iter;
if(iter != vecTasklist.end())
{
task = *iter;
vecTasklist.erase(iter);
}
pthread_mutex_unlock(&pthreadMutex);
task->Run();
printf("[tid: %lu]\tidle\n", tid);
}
return (void*)0;
}
int CThreadPool::AddTask(CTask *task)
{
pthread_mutex_lock(&pthreadMutex);
vecTasklist.push_back(task);
pthread_mutex_unlock(&pthreadMutex);
pthread_cond_signal(&pthreadCond);
return 0;
}
int CThreadPool::Create()
{
pthread_id = new pthread_t[threadNum];
for(int i = 0; i < threadNum; i++)
pthread_create(&pthread_id[i], NULL, ThreadFunc, NULL);
return 0;
}
int CThreadPool::StopAll()
{
if(shutdown)
return -1;
cout << "i will end all thread" << endl;
shutdown = true;
pthread_cond_broadcast(&pthreadCond);
for (int i = 0; i < threadNum; i++)
pthread_join(pthread_id[i], NULL);
delete[] pthread_id;
pthread_id = NULL;
pthread_mutex_destroy(&pthreadMutex);
pthread_cond_destroy(&pthreadCond);
return 0;
}
int CThreadPool::getTaskSize()
{
return vecTasklist.size();
}
- main.cpp
#include "threadPool.h"
#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <unistd.h>
class CMyTask : public CTask
{
public:
CMyTask() = default;
int Run()
{
printf("%s\n", (char *)ptrData);
int x = rand() % 4 + 1;
sleep(x);
return 0;
}
~CMyTask(){}
};
int main()
{
CMyTask taskObj;
char szTmp[] = "hello comedy";
taskObj.setData((void*)szTmp);
CThreadPool threadpool(5);
for (int i = 0; i < 10; i++)
threadpool.AddTask(&taskObj);
while(1)
{
printf("There are still %d tasks need to handle\n",threadpool.getTaskSize());
if(threadpool.getTaskSize()==0)
{
if(threadpool.StopAll() == -1)
{
printf("Thread pool clear, exit.\n");
exit(0);
}
}
sleep(2);
cout << "2 seconds later..." << endl;
}
return 0;
}
运行结果如图所示:
程序稳定运行,留着以后要用的时候参考。