14、线程池
1、为什么需要线程池
-
服务器都具有一个共同点:单位时间内必须处理很多并发的连接请求,但处理时间却相对较短.
-
传统多线程方案中我们采用的服务器模型则是一旦接受到请求之后,即创建一个新的线程,由该线程执行任务.任务执行完毕后,线程退出,这就是是"即时创建,即时销毁"的策略.
-
尽管与创建进程相比,创建线程的时间已经大大的缩短,但是如果提交给线程的任务是执行时间较短,而且执行次数及其频繁,那么服务器将处于不停的创建线程,销毁线程的状态.
-
线程池是采用多线程解决方案来提高系统性能的一个最为出色的模型,它通过预创建一定数量的工作线程来对系统进行并发处理,使得系统的运行效率提高.因为线程池能使得系统采用较为轻量的,可控的系统资源实现系统并发处理能力的最大化,所以许多应用软件都采用了线程池模型.
-
通常线程池所允许的并发线程具有上界的,如果同时需要并发的线程数超过上界,那么一部分线程将等待.而传统方案中,如果同时请求数据为200,那么最坏情况下,系统可能需要产生200个线程.尽管这不是一个很大的数目,但是也有系统达不到这个要求.
-
线程池模型有许多种,常见的有三种:
-
任务队列控制的线程池模型,
-
工作线程控制的线程池模型,
-
主控线程控制的线程池模型.
-
2、任务队列控制的线程池模型
任务队列控制的线程模型主要是通过任务队列上的信号来控制线程池中的线程调度。
3、线程池适合场合
-
事实上,线程池并不是万能的。它有其特定的使用场合。线程池致力于减少线程本身的开销对应用所产生的影响,这是有前提的,前提就是线程本身开销与线程执行任务相比不可忽略。
-
如果线程本身的开销相对于线程任务执行开销而言是可以忽略不计的,那么此时线程池所带来的好处是不明显的,比如对于FTP服务器以及Telnet服务器,通常传送文件的时间较长,开销较大,那么此时,我们采用线程池未必是理想的方法,我们可以选择“即时创建,即时销毁”的策略。
-
总之线程池通常适合下面的几个场合:
-
(1) 单位时间内处理任务频繁而且任务处理时间短
-
(2) 对实时性要求较高。如果接受到任务后在创建线程,可能满足不了实时要求,因此必须采用线程池进行预创建。
-
(3) 必须经常面对高突发性事件,比如Web服务器,如果有足球转播,则服务器将产生巨大的冲击。此时如果采取传统方法,则必须不停的大量产生线程,销毁线程。此时采用动态线程池可以避免这种情况的发生
-
4、线程池C++版本
//CPthreadPool.h
#ifndef _CPTHREADPOOL_H_
#define _CPTHREADPOOL_H_
#include <stdio.h>
#include <pthread.h>
#include <list>
#include <iostream>
#include <string.h>
#include "CPthreadCond.h"
#include "CTask.h"
class CPthreadPool
{
public:
CPthreadPool(int minpthread, int maxpthread, int timeout = -1);
//~CPthreadPool();
void create_pthread();
static void *hander(void *arg);
void addtask(CTask *data);
int inowpthread;
int waitpthread;
int maxpthread;
int minpthread;
int timeout;
CPthreadCond cond;
list<CTask *>hander_list;
};
#endif
//CPthreadPool.cpp
#include "CPthreadPool.h"
CPthreadPool::CPthreadPool(int minpthread, int maxpthread, int timeout)
{
this->timeout = timeout;
this->minpthread = minpthread;
this->maxpthread = maxpthread;
this->inowpthread = 0;
this->waitpthread = 0;
this->cond.lock();
for(int i = 0; i < this->minpthread; i++)
{
this->create_pthread();
}
this->cond.unlock();
}
void CPthreadPool::create_pthread()
{
this->inowpthread++;
pthread_t pth = 0;
pthread_create(&pth, NULL, hander, (void *)this);
//printf("create %d pthread\n", this->inowpthread);
}
void *CPthreadPool::hander(void *arg)
{
pthread_detach(pthread_self());
CPthreadPool *pool = (CPthreadPool *)arg;
while(1)
{
pool->cond.lock();
if(!pool->hander_list.empty())//Get one task and do it.
{
CTask *task = pool->hander_list.front();
pool->hander_list.pop_front();// Remove from task list.
pool->cond.unlock();
task->Run();
delete task;
}
else
{
pool->waitpthread++;
if(pool->cond.timewait(pool->timeout))
{
pool->waitpthread--;
pool->cond.unlock();
if(pool->inowpthread > pool->minpthread)
{
//cout << 444 << pool->inowpthread << pool->minpthread << endl;
pool->inowpthread--;
break;
}
}
else
{
//cout << 200 <<endl;
pool->waitpthread--;
pool->cond.unlock();
}
}
}
pthread_exit(NULL);
}
void CPthreadPool::addtask(CTask *data)
{
hander_list.push_back(data);
if(this->waitpthread > 0)
{
this->cond.signal();
//cout << "唤醒\n" << endl;
}
else if(this->inowpthread < this->maxpthread)
{
this->create_pthread();
//cout << "创建线程!\n" << this->inowpthread << endl;
}
}