为什么要有线程池呢?
- 因为在完成用户发起的一个请求任务后,这个任务从发起请求到结束任务都会经历一个过程:
若大量的任务处理总耗时 t 中线程的创建 t1 与线程的销毁 t2 占用了大量的比例,就意味着资源、性能的浪费。在大量请求的峰值压力下,若每个请求都创建一个线程,则有可能导致资源耗尽,程序崩溃。所以才会有线程池的出现来解决这个问题。
线程池的应用场景?
-
任务量大,并且完成任务的时间比较短。(也就是 t2 < t1 + t3)
WEB服务器完成网页请求这样的任务,使用线 程池技术是非常合适的。因为单个任务小,而任务数量巨大,你可以想象一个热门网站的点击次数。 但对于长时间的任 务,比如一个Telnet连接请求,线程池的优点就不明显了。因为Telnet会话时间比线程的创建时间大多了。
-
对性能要求苛刻的应用,比如要求服务器迅速响应客户请求。
什么是线程池呢?
-
提前创建一大堆线程,以及一个线程安全的任务队列,当大量的请求到来之后就被添加到任务队列中,而线程池当中的线程在不断的从任务队列获取任务进行处理。
PS:当然这个线程数量也是有最大数量限制的,创建过多也有可能面临资源耗尽的风险;其实任务队列中的任务数量也是有最大数量限制的,过多也有可能面临资源耗尽的风险。
线程池的作用?
- 避免了大量创建线程、销毁线程带来的时间成本。
- 避免了峰值压力下线程创建的过多而导致资源耗尽的风险。
线程池的实现:
#include <iostream>
#include <queue>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
typedef void (*TaskHandler)(int data);//定义了一个函数指针
class ThreadTask {
//这是一个任务类,用户发起任务请求后就将一个ThreadTask对象在ThreadPool的任务队列中进行添加
private:
int _data;
TaskHandler _handler;
public:
ThreadTask(){}
ThreadTask(int data, TaskHandler handler):_data(data),
_handler(handler) {}
void SetTask(int data, TaskHandler handler) {
_data = data;
_handler = handler;
}
void Run() {
_handler(_data);
}
};
#define MAX_THR 5
class ThreadPool {
private:
int thr_num;//线程池中线程的最大数量
std::queue<ThreadTask> _task_queue;//队列
pthread_mutex_t _mutex;//保护队列安全操作
pthread_cond_t _cond_con;//实现队列的同步操作--消费者
pthread_cond_t _cond_pro;//实现队列的同步操作--生产者
private:
static void *thr_start(void *arg)
{
ThreadPool *pool = (ThreadPool*)arg;
while(1) {
pool->ThreadLock();
while(pool->TaskIsEmpty()) {
pool->ThreadWait();
}
ThreadTask tt;
pool->QueuePop(tt);
pool->ThreadUnLock();
tt.Run();
}
return NULL;
}
public:
bool QueuePop(ThreadTask &tt) {
std::cout << _task_queue.size() << "\n";
tt = _task_queue.front();
_task_queue.pop();
return true;
}
void ThreadWait() {
pthread_cond_wait(&_cond_con, &_mutex);
}
void ThreadWakeUp() {
pthread_cond_signal(&_cond_con);
}
bool TaskIsEmpty() {
return _task_queue.empty();
}
void ThreadLock() {
pthread_mutex_lock(&_mutex);
}
void ThreadUnLock() {
pthread_mutex_unlock(&_mutex);
}
public:
ThreadPool(int max_thr = MAX_THR): thr_num(max_thr){}
bool PoolInit() {
pthread_mutex_init(&_mutex, NULL);
pthread_cond_init(&_cond_con, NULL);
pthread_cond_init(&_cond_pro, NULL);
for (int i = 0; i < thr_num; i++) {
pthread_t tid;
int ret = pthread_create(&tid,NULL,thr_start,(void*)this);
if (ret != 0) {
std::cerr << "create thread error\n";
return false;
}
pthread_detach(tid);
}
return true;
}
bool TaskPush(ThreadTask &tt) {
pthread_mutex_lock(&_mutex);
_task_queue.push(tt);
pthread_mutex_unlock(&_mutex);
pthread_cond_signal(&_cond_con);
return true;
}
};
void test(int data)
{
srand(data);
int sec = rand() % 5;
printf("thread:%p--get data:%d , sleep %d sec\n", pthread_self(),
data, sec);
sleep(sec);
}
int main()
{
ThreadPool pool;
pool.PoolInit();
for (int i = 0; i < 10; i++) {
ThreadTask task(i, test);
pool.TaskPush(task);
}
while(1) {
sleep(1);
}
return 0;
}