c/c++线程--3
最近一段时间在看linux下c语言的多线程,其中一个比较重要的应用就是线程池。自己也参照着网上的资料写了一个简单的线程池。这里做以总结。
1.解决问题,应用场景
我们的应用在任何时候都要准备应对数目巨大的连接请求,同时,这些请求所要完成的任务却又可能非常的简单,即只占用很少的处理时间。总之线程池通常适合下面的几个场合:
(1) 单位时间内处理任务频繁而且任务处理时间短
(2) 对实时性要求较高。如果接受到任务后在创建线程,可能满足不了实时要求,因此必须采用线程池进行预创建。
(3) 必须经常面对高突发性事件,比如Web服务器,如果有足球转播,则服务器将产生巨大的冲击。此时如果采取传统方法,则必须不停的大量产生线程,销毁线程。此时采用动态线程池可以避免这种情况的发生。
目的很明确,为了减少创建销毁带来的开销,尤其是当线程的任务简单的时候。
2. 设计思路
一般来说,线程池都是采用预创建的技术,在应用启动之初便预先创建一定数目的线程。应用在运行的过程中,需要时可以从这些线程所组成的线程池里申请分配一个空闲的线程,来执行一定的任务。
任务完成后,并不是将线程销毁,而是将它返还给线程池,由线程池自行管理。如果线程池中预先分配的线程已经全部分配完毕,但此时又有新的任务请求,则线程池会动态的创建新的线程去适应这个请求。
当然,有可能,某些时段应用并不需要执行很多的任务,导致了线程池中的线程大多处于空闲的状态,为了节省系统资源,线程池就需要动态的销毁其中的一部分空闲线程。
因此,线程池都需要一个管理者,按照一定的要求去动态的维护其中线程的数目。3. 核心模型
创建的线程都要从这里开始执行。
threadRoutine()
{
while(1)
{
lock();
while(0 == queueSize && notShutDown) /// 如果没有任务,在这里等待
{
wait();
}
if(!notShutDown) /// 在这里结束任务。
{
exit();
}
if(queueSize > 0)
{
mission = queue.pop();
unlock();
runMission();
}
else
{
unlock();
}
}
}
4. 简单线程池代码
头文件
/**
purpose : 基本线程池
实现缓冲外部高并发任务数
author : oslo wang
data : 2015 05 19
next Version : 这里没有实现对线程池里线程的动态管理。
如果空闲线程多,则销毁一些。
如果等待的任务多,则创建一些线程。
*/
#include <pthread.h>
#include <queue>
/// 采用c++ stl中的队列来管理任务。
using std::queue;
/// 线程任务结构体
typedef struct st_threadMission
{
void *(*process) (void *arg);
void * arg;
} threadMission;
threadMission * createThreadMission(void* (*process) (void *), void *arg);
/// 简单线程池类
class CThreadPool
{
public:
CThreadPool(int maxThread = 10);
~CThreadPool();
bool InitPool(int maxThread = 10);
bool DestrPool();
void addMission(threadMission * mission);
//void * threadRoutine(void *arg);
static void * threadRoutine(void *arg);
private:
pthread_mutex_t mutex; /// 和条件变量一起使用的互斥锁
pthread_cond_t hasMission; /// 条件变量,用于通知有任务处理。
queue<threadMission*> missionQueue;
pthread_t* threadId;
unsigned int maxThreadInPool;
bool isShutDown;
};
//void * threadRoutine(void *arg);
int ThreadPool_Test();
实现
#include "ThreadPool.h"
#include <stdio.h>
#include <unistd.h>
CThreadPool::CThreadPool(int maxThread)
{
InitPool(maxThread);
}
CThreadPool::~CThreadPool()
{
DestrPool();
}
bool CThreadPool::InitPool(int maxThread)
{
printf("\nInitial Thread Pool.\n\n");
if(maxThread <= 0)
maxThread = 10;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&hasMission, NULL);
isShutDown = false;
maxThreadInPool = maxThread;
threadId = new pthread_t[maxThreadInPool];
unsigned int i;
for(i = 0; i < maxThreadInPool; ++i)
{
if(0 != pthread_create(&threadId[i], NULL, threadRoutine, this))
{
printf("error in CThreadPool::InitPool(), i = %d.\n", i);
}
}
return true;
}
bool CThreadPool::DestrPool()
{
if(isShutDown)
return true;
printf("\nDestroy Thread Pool.\n\n");
isShutDown = true;
pthread_cond_broadcast(&hasMission);
int i;
for(i = 0; i < maxThreadInPool; ++i)
{
pthread_join(threadId[i], NULL);
}
delete[] threadId;
threadId = NULL;
threadMission *ptr = NULL;
int queueNum = missionQueue.size();
for(i = 0; i < queueNum; ++i)
{
ptr = missionQueue.front();
missionQueue.pop();
delete ptr;
}
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&hasMission);
return true;
}
void CThreadPool::addMission(threadMission * mission)
{
pthread_mutex_lock(&mutex);
missionQueue.push(mission);
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&hasMission);
}
void * CThreadPool::threadRoutine(void *arg)
{
pthread_t tid = pthread_self();
printf ("starting thread 0x%lu\n", tid);
CThreadPool *ptr = (CThreadPool *)arg;
while(1)
{
pthread_mutex_lock(&ptr->mutex);
while(0 == ptr->missionQueue.size() && !ptr->isShutDown)
{
printf("thread 0x%lu is waiting.\n", tid);
pthread_cond_wait(&ptr->hasMission, &ptr->mutex);
}
/**线程在这里销毁*/
if(ptr->isShutDown)
{
pthread_mutex_unlock(&ptr->mutex);
printf("thread 0x%lu will exit.\n", tid);
pthread_exit(NULL);
}
threadMission * mission = NULL;
if(ptr->missionQueue.size() > 0)
{
mission = ptr->missionQueue.front();
ptr->missionQueue.pop();
pthread_mutex_unlock(&ptr->mutex);
void* (*process) (void *arg) = mission->process;
void * arg = mission->arg;
process(arg);
delete mission;
mission = NULL;
}
else
{
pthread_mutex_unlock(&ptr->mutex);
}
}
pthread_exit(NULL);
return NULL;
}
char argString[5][256] = { "Hello World.",
"Can you do this?",
"Holy shit!",
"rampage!",
"Could you play DOTA?"
};
void * myprocess(void *arg)
{
char *str = (char*)arg;
printf("\nthread %lu\n", pthread_self());
printf("#######arg : %s\n\n", str);
sleep(1);
return NULL;
}
threadMission * createThreadMission(void* (*process) (void *), void *arg)
{
threadMission * tmp = new threadMission;
tmp->process = process;
tmp->arg = arg;
return tmp;
}
int ThreadPool_Test()
{
CThreadPool cp1(7);
int i;
threadMission *mission = NULL;
for(i = 0; i < 5; ++i)
{
mission = createThreadMission(myprocess, argString[i]);
cp1.addMission(mission);
}
sleep(10);
return 0;
}