线程池是预先创建线程的一种技术。线程池在还没有任务到来之前,创建一定数量的线程,放入空闲队列中。这些线程都是处于睡眠状态,即均为启动,不消耗CPU,而只是占用较小的内存空间。当请求到来之后,缓冲池给这次请求分配一个空闲线程,把请求传入此线程中运行,进行处理。当预先创建的线程都处于运行状态,即预制线程不够,线程池可以自由创建一定数量的新线程,用于处理更多的请求。当系统比较闲的时候,也可以通过移除一部分一直处于停用状态的线程。
诸如web服务器、数据库服务器、文件服务器和邮件服务器等许多服务器应用都面向处理来自某些远程来源的大量短小的任务。构建服务器应用程序的一个过于简单的模型是:每当一个请求到达就创建一个新的服务对象,然后在新的服务对象中为请求服务。但当有大量请求并发访问时,服务器不断的创建和销毁对象的开销很大。所以提高服务器效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁,这样就引入了“池”的概念,“池”的概念使得人们可以定制一定量的资源,然后对这些资源进行复用,而不是频繁的创建和销毁。
//c_task.h
#ifndef _C_TASK_H
#define _C_TASK_H
#include
class CTask
{
protected:
std::string taskName;
void * ptrData;
public:
CTask(){} virtual int runBody() = 0;
inline void setData(void *data) { ptrData = data;}
};
#endif
这是c_task.h头文件,它定义了一个任务基类CTask,该任务基类很简单提供了一个私有保护的数据指针,和一个公有的设置指针的方法,注意到其中的一个虚函数runBody,它是具体任务的执行体,这里把它设置为虚函数是为了留给子类重载,从而实现了多态。
接下来定义子任务类来继承任务基类。
//my_task.h
#ifndef _MY_TASK_H
#define _MY_TASK_H
#include "c_task.h"
class MyTask : public CTask
{
public:
virtual int runBody();
};
#endif
这个具体任务类也非常简单,仅仅重载了父类的runBody方法,接下来是这个类的实现,其实这个类的实现:
//my_task.cpp
#include
using namespace std;
int MyTask::runBody()
{
std::string res(static_cast(ptrData));
cout << res << endl;
return 0;
}
接下来就是最主要的线程池的管理类了,看它的定义:
#ifndef _THREAD_POOL_H
#define _THREAD_POOL_H
#include
#include
#include "my_task.h"
class ThreadPool
{
private:
static std::vector vecThreadId;
std::vector vecTaskList;
int threadNum;
static void *threadFunc(void *data);
int createAll();
public:
static pthread_cond_t vecTaskCond;
static pthread_mutex_t vecTaskMutex;
ThreadPool(int num);
~ThreadPool();
int stopAll();
int addTask(CTask *task);
};
#endif
这里面的成员数量较多。因为它至少要包含一个任务队列,一个添加任务方法,启动线程池和关闭线程池的方法,另外就是要控制线程同步所必要的锁和条件变量了。下面看看它的实现
#include "thread_pool.h"
using namespace std;
std::vector ThreadPool::vecThreadId;
pthread_mutex_t ThreadPool::vecTaskMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t ThreadPool::vecTaskCond = PTHREAD_COND_INITIALIZER;
ThreadPool::ThreadPool(int num)
{
threadNum = num;
createAll();
}
ThreadPool::~ThreadPool()
{
stopAll();
}
int ThreadPool::addTask(CTask *task)
{
pthread_mutex_lock(&vecTaskMutex);
vecTaskList.push_back(task);
if(vecTaskList.size() == 1)
{
pthread_cond_signal(&vecTaskCond);
}
pthread_mutex_unlock(&vecTaskMutex);
return 0;
}
void* ThreadPool::threadFunc(void *data)
{
while(1)
{
pthread_mutex_lock(&vecTaskMutex);
std::vector* vecTask = static_cast*>(data);
while(vecTask->size() == 0)
{
pthread_cond_wait(&vecTaskCond, &vecTaskMutex);
}
std::vector::iterator iter = vecTask->begin();
CTask *task = *iter;
vecTask->erase(iter);
pthread_mutex_unlock(&vecTaskMutex);
int ret = task->runBody();
delete (char*)task->ptrData;
delete task;
}
return 0;
}
int ThreadPool::createAll()
{
for(int i = 0; i < threadNum; i++)
{ pthread_t tid = 0;
pthread_create(&tid, 0, threadFunc, (void*)&vecTaskList);
vecThreadId.push_back(tid);
}
return 0;
}
int ThreadPool::stopAll()
{
std::vector::iterator iter = vecThreadId.begin();
while(iter != vecThreadId.end())
{
pthread_cancel(*iter);
pthread_join(*iter, NULL);
iter++;
}
return 0;
}
到这里我们的线程池就写完了,下面我们可以写一个main函数来测试一下。
//main.cpp
#include "my_task.h"
#include "thread_pool.h"
#include
using namespace std;
int main()
{
ThreadPool *threadPool = new ThreadPool(10);
while(1)
{
string stringBuff = "test ThreadPool";
char* buf = new char[stringBuff.size() + 1];
bzero(buf, stringBuff.size()+1);
strcpy(buf, stringBuff.c_str());
CTask* myTask = new MyTask();
myTask->setData(buf);
threadPool->addTask(jsonTask);
sleep(1);
}
delete threadPool;
return 0;
}
运行测试就不给大家贴出来了,代码中还有很多不好的地方
4、参考文献
线程池介绍部分摘自:http://www.cnblogs.com/coser/archive/2012/03/10/2389264.htm