# ThreadPool 线程池

## 软件中的池是什么?

池 可以理解为 程序运行的计划经济. 比如 线程池, 所有的任务需要拿到 线程池中的线程才能被运行. 这就好比计划经济时代, 老百姓要想买米, 必须拿到粮票一样.&#x20;

为什么要使用线程池?

1. 如果不使用线程池, 每一个任务都需要新开一个线程. 频繁地创建和销毁线程 开销是非常大的.&#x20;
2. 过多的线程会占用过多的内存

我们希望有 固定数量的线程 或者 一定数量范围的线程 来处理大量的任务, 这就是线程池

### 线程池构造方法的参数

| 参数名           | 类型                       | 含义                                     |
| ------------- | ------------------------ | -------------------------------------- |
| corePoolSize  | int                      | 核心线程数                                  |
| maxPoolSize   | int                      | 最大线程数                                  |
| keepAliveTime | long                     | 保持存活时间                                 |
| workQueue     | BlockingQueue            | 任务存储队列                                 |
| threadFactory | ThreadFactory            | 当线程池需要新的线程的时候, 会使用threadFactory来生成新的线程 |
| Handler       | RejectedExecutionHandler | 由于线程池无法处理新的任务的拒绝策略                     |

#### corePoolSize&#x20;

线程池在完成初始化后, 默认情况下, 线程池中没有任何线程. 当线程池遇到新任务时, 创建新线程去执行任务.

#### maxPoolSize&#x20;

在核心线程数的基础上, 额外增加的线程数的上限

### 线程添加规则

1. 如果线程数小于corePoolSize, 创建一个新线程来执行新任务
2. 如果线程数大于等于corePoolSize但少于maximumPoolSize, 则将任务放入队列
3. 如果队列已满, 并且线程数量小于maxPoolSize, 则创建一个新线程
4. 如果队列已满, 并且线程数大于等于maxPoolSize, 则拒绝

比喻: 大排档的桌子

1. 如果室内还有桌子, 那就让新来的客人到室内就餐
2. 如果室内坐姿满了, 则排队
3. 如果排队的人太多了, 室外还有桌子, 那就室外就餐
4. 如果排队的人太多了, 室外也没有桌子, 那就送客

#### keepAliveTime

如果线程池当前的先册灰姑娘数大于corePoolSize, 那么如果多余的先册灰姑娘空闲时间超过keepAliveTime, 它就会被终止

#### workQueue

有3种最常见的队列类型

1. SynchronousQueue 直接交接, 任务经过队列直接交给线程池, 相当于队列容量为0
2. LinkedBlockingQueue 无界队列, 任务会一直放入队列
3. ArrayBlockingQueue 有界队列, 队列满了之后创建新线程或者拒绝
