一.线程池
线程池:大量线程(数量存在上限)+线程安全的任务队列
T1(线程创建)+T2(任务处理)+T3(线程销毁) = T(任务处理总时间)
在一个任务处理的总时间中,若T1+T3所占用的时间占用大量的比例,也就意味着大量任务的处理中,资源被浪费在线程的创建和销毁中,这是不合理的.
因此产生了线程池,创建出大量线程(并不退出),而是不断将任务交给这些线程进行处理.
避免了大量线程创建/销毁所带来的时间成本.
注意: 线程池中线程的数量是有上限的,避免出现峰值压力,瞬间资源被耗尽导致程序崩溃的危险.
二.线程池的实现
线程池中任务队列节点应该包含两个元素:
- 要处理的数据
- 这个数据对应的处理方法
任务队列:
typedef void (*handler_t)(int);
//任务类:包含数据(_fd)以及处理数据(handler_t)的方法
class ThreadTask{
public:
//无参构造和带参构造
ThreadTask(){}
ThreadTask(int data,handler_t hander)
:_data(data)
,_handler(hander){}
//设置任务:将数据以及处理数据的方法添加到线程任务当中
void SetTask(int data,handler_t hander){
_data = data;
_handler = hander;
return;
}
//利用处理数据的方法处理数据
void Run(){
return _handler(_data);
}
private:
int _data; //数据
handler_t _handler;//处理数据的方法
};
线程池的实现:线程安全利用互斥锁和条件变量实现
#define THR_MAX 5 //创建线程的个数
#define QUE_MAX 10 //线程安全的任务队列的节点最大值
//线程池:
class ThreadPoll{
public:
//初始化线程池:初始化互斥量和条件变量(保存线程安全),创建出线程,并且分离线程
ThreadPoll(int thr_max = THR_MAX,int que_max = QUE_MAX){
pthread_mutex_init(&_mutex,NULL);
pthread_cond_init(&_cond_pro,NULL);
pthread_cond_init(&_cond_cus,NULL);
int ret;
pthread_t tid;
for(int i = 0;i < thr_max;i++){
ret = pthread_create(&tid,NULL,thr_start,this);
if(ret != 0){
std::cout << "create thread error" << std::endl;
exit(-1);
}
pthread_detach(tid); //分离线程:不关心线程退出返回值 线程结束自动释放资源,不需要线程等待
}
}
//线程池析构:销毁条件变量以及互斥量
~ThreadPoll(){
pthread_mutex_destroy(&_mutex);
pthread_cond_destroy(&_cond_pro);
pthread_cond_destroy(&_cond_cus);
}
//将任务添加至任务队列:
bool TaskPush(const ThreadTask& task){
pthread_mutex_lock(&_mutex); //互斥锁上锁
while(_queue.size() == _capacity){ //当任务队列满时,生产者线程进行等待
pthread_cond_wait(&_cond_pro,&_mutex);
}
_queue.push(task);
pthread_mutex_unlock(&_mutex); //解锁
pthread_cond_signal(&_cond_cus); //唤醒消费者进行消费
return true;
}
//线程入口函数:线程的任务就是从任务队列中取出任务,然后用处理数据的方法处理数据
static void* thr_start(void* arg){
ThreadPoll* pool = (ThreadPoll*)arg;
while(1){
pthread_mutex_lock(&pool->_mutex);
while(pool->_queue.empty()){
pthread_cond_wait(&pool->_cond_cus,&pool->_mutex);
}
ThreadTask task;
task = pool->_queue.front();
pool->_queue.pop();
pthread_mutex_unlock(&pool->_mutex);
pthread_cond_broadcast(&pool->_cond_pro); //唤醒所有被阻塞的生产者线程
task.Run();//调用处理数据的方法处理数据
}
return NULL;
}
private:
int _thread_max; //可创建线程的最大值
int _capacity; //任务队列节点的最大值
std::queue<ThreadTask> _queue; //存放任务的队列
pthread_mutex_t _mutex; //互斥锁
pthread_cond_t _cond_pro; //生产者
pthread_cond_t _cond_cus; //消费者
};