今天,笔者想来介绍一下线程池这个东西。

什么是线程池呢?为啥要有这么一个东西?
我们可以把线程比作一个池子,里面有很多线程。同样线程池和线程之间的关系也可以比作饭桶和饭勺的关系。我们知道,线程是一种稀缺资源,对多个线程进行调度,创建,销毁需要一定的开销,而饭桶中的饭勺也可以算作是一个稀缺资源,因为一个饭桶中的饭勺最多也就那么几个,如果每个人打饭都首先需要向食堂阿姨申请要个饭勺(创建线程),打饭,打完饭之后还给食堂阿姨(线程销毁),想象一下也是可以感触到,这样做的效率是比较低下的(毕竟打饭的人这么多,如果每个人都按这个流程走一遍,可能午饭就变成晚饭了)。所以呢,我们的食堂阿姨还是很聪明的,直接放几个(一定数量)的饭勺到饭桶了,每个人排队打饭,打饭的时候直接在饭桶里拿饭勺,用完放回饭桶里,以便他人使用,这样打饭的效率就高了。所以在一定程度上,我们可以把饭桶比作线程池,而饭勺就是线程池中的线程。

接下来来点专业点的东西
1.线程过多会带来调度开销,进而影响缓存局部性和整体性能。
2.线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。
3.线程池避免了在处理短时间任务时创建与销毁线程的代价。
4.线程池不仅能够保证内核的充分利用,还能防止过分调度。
5.线程数一般取cpu数量+2比较合适,线程数过多会导致额外的线程切换开销。
------摘自百度百科:D

线程池模式
线程池模式一般分为两种:HS/HA半同步/半异步模式、L/F领导者与跟随者模式。
1.半同步/半异步模式又称为生产者消费者模式,是比较常见的实现方式,比较简单。分为同步层、队列层、异步层三层。同步层的主线程处理工作任务并存入工作队列,工作线程从工作队列取出任务进行处理,如果工作队列为空,则取不到任务的工作线程进入挂起状态。由于线程间有数据通信,因此不适于大数据量交换的场合。

2.领导者跟随者模式,在线程池中的线程可处在3种状态之一:领导者leader、追随者follower或工作者processor。任何时刻线程池只有一个领导者线程。事件到达时,领导者线程负责消息分离,并从处于追随者线程中选出一个来当继任领导者,然后将自身设置为工作者状态去处置该事件。处理完毕后工作者线程将自身的状态置为追随者。这一模式实现复杂,但避免了线程间交换任务数据,提高了CPU cache相似性。在ACE(Adaptive Communication Environment)中,提供了领导者跟随者模式实现。

注意:
1.创建太多线程,将会浪费一定的资源,有些线程未被充分使用。
2.销毁太多线程,将导致之后浪费时间再次创建它们。
3.创建线程太慢,将会导致长时间的等待,性能变差。
4.销毁线程太慢,导致其它线程资源饥饿。

线程池的组成部分:
1、线程池管理器(ThreadPoolManager):用于创建并管理线程池
2、工作线程(WorkThread): 线程池中线程
3、任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行。
4、任务队列:用于存放没有处理的任务。提供一种缓冲机制。

关于"池化思想"的理解
这里有一篇我在网上找到的博客,感觉解释的还不错,可以看看
链接:https://www.cnblogs.com/cblpolly/p/11065656.html

这一节就先到这,下一节开始使用C++11的特性来实现一个线程池。:D