**
线程池
**
线程池是什么?
线程池是线程安全的更加具体的应用。
线程池主要还是一种任务处理的思路,对于大量的任务或者数据进行处理的场景。
对于大量的请求任务,单个线程是无法承载的,所以我们需要多个执行流。
第一种想法:
来一个任务,创建一个线程,处理任务,然后销毁线程。
缺点:
1、在大量峰值下,需要创建大量的线程,消耗大量的资源,系统崩溃
2、创建线程时间T1,处理任务T2,销毁线程T3,如果T1+T2时间过多,不合理。
针对上边想法的改进,我们提出了线程池这个东西。
有一个或者多个线程 对任务进行处理的实体叫做线程池。(线程处理任务是靠入口函数)
线程池包括什么?
有数量上限的线程+线程安全的任务队列
1、线程池中线程是提前创建好的,因为有上限,所以资源不会消耗。
2、线程不断的从任务队列中取出任务进行处理。
优点
1、避免了大量创建线程和销毁线程带来的时间成本。
2、避免了当大量请求任务来了之后,短时间创建大量线程导致系统崩溃。
3、线程池不仅能够保证内核的充分利用,还能防止过分调度(没有了cpu的调度)。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量。
一般的线程的入口函数
都是在创建线程的时候,就固定传入的什么函数名。void的函数参数*。,会导致线程池中的线程任务处理的方式过于单一。
但是线程池中的线程
我们在任务队列中不仅传入数据,还传入数据处理的方法。所以线程池中的线程只需要传入的方法,处理的数据就好了,但是不管是什么方法,什么数据,如何处理。
线程的应用场景:
1、需要大量的线程来完成任务,并且任务处理的时间短。例如web服务器完成网页的请求这样的任务。
2、对性能要求苛刻的应用。例如服务器迅速响应客户。
3、能够接受突发性的大量任务请求。虽然操作系统线程数组最大值没有问题,但是短时间产生大量线程可能使内存达到极限,系统崩溃。
线程池的实现
//实现了消费者线程(就是线程池中提前生成的线程) 的生产者消费者模型
//先定义一个池子
#define MAX_THREAD 5//定义一个宏,表示线程池中的最大线程个数
class ThreadPool
{
private:
int thr_max;//定义线程池中线程的最大数量,初始化时创建相应数量的线程即可。
std::queue<MyTask> _queue;//放任务的队列,对于任务队列里边的任务,它有数据还有处理方式,所以这个任务应该是自定义的。
~~~~int capacity~~ ;~~ //这个容量是不需要的,在第一个消费者生产者模型里边queue需要大小,防止内存被耗尽,但是线程池里边是不需要capacity的,因为任务总会被线程处理掉,,老师第二遍讲的时候queue给大小了,并且建立了cond_cus和cond_pro,其实都差不多
pthread_mutex_t mutex;//线程池一定要是安全的,所以要有锁子
pthread_cond_t cond;//线程池中的消费者需要同步进行,需要一个条件。而且只需要消费者的同步,生产者是在外部的,不影响的
public:
ThreadPool(int max = MAX_THREAD)//缺省参数
:thr_max(max)
{
pthread_mutex_init(&mutex,NULL);
pthread_cond_inint(&cond,NULL);
///因为消费者的线程是出现在线程池中的,所以消费者者的线程在线程池的创建中,也应该创建出来
for(int i = 0; i < thr_max;i++)
{
pthread_t tid;
int ret = pthread_create(&tid,NULL,thr_start,this);//传递的这个this看下边的thr_start那里
if(ret != 0)
{
printf("线程创建失败了");
exit(0);
}
}
}
~ThreadPool()
{
pthread_mutex_destory(&mutex,NULL);
pthread_cond_destory(&cond,NULL);
}
//外部的生产者生产任务,将数据与处理方式放到任务队列中,外部的生产者函数入口应该在线程池的外部,跟前边的消费者生产者模型是一样的。但是消费者的线程入口函数应该在线程池内部,因为消费者线程本身就应该在线程池内部
bool PushTask(ThreadTask& task)
{
//生产者要访问queue,所以加锁
pthread_mutex_lock(&mutex);
///如果这里queue有大小,要注意入队判断queue是不是满了,满了需要阻塞使用pthread_cond_wait(&cond_pro,&mutex)//这里如果queue有大小了,那就必须得来一个cond_pro的条件队列。因为队列满了,需要生产者进行等待的,这时候用一个cond等待队列就会有问题。
queue.