# ThreadPoolExecutor - 从JDK11源码理解Java线程池原理

## 1 表层——Executors

JDK对外提供Executors类的三个静态方法供调用，可以快速生成线程池：

## 2 深一层——ThreadPoolExecutor

ThreadPoolExecutor提供构造函数：

• 核心线程池尺寸：线程池至少保有多少线程；
• 最大线程池尺寸：线程池最多能创建多少线程；
• 保活时间：线程数量如果超过核心线程数了，最多允许空闲多久，超过即终止线程；
• 时间单位：保活时间的时间单位，可以是纳秒、微秒、毫秒、秒、分钟、小时、天；
• 工作队列：提交给线程池的任务在执行前，会先放到工作队列中。

### 2.1 newSingleThreadExecutor

newSingleThreadExecutor具体设置参数为：

• 核心线程数和最大线程数都是1，这保证了线程池中有且只有一个线程。
• 因为只有1个线程，所以无所谓超时终止，因此保活时间为0。
• 提交给线程池的线程会放到一个LinkedBlockingQueue的实例中。
• 这是一个默认无界的阻塞队列（可选有界以控制内存消耗）。

• 只是实现了finalize方法，负责关闭线程池。

### 2.2 newFixedThreadPool

newFixedThreadPool具体设置参数为：

• 核心线程数和最大线程数都是输入参数nThreads，这保证了线程池中有且只有nThreads个线程。
• 因为只有nThreads个线程，所以无所谓超时终止，因此保活时间为0。
• 提交给线程池的线程会放到一个LinkedBlockingQueue的实例中。

### 2.3 newCachedThreadPool

newCachedThreadPool具体设置参数为：

• 核心线程数为0，意味着如果线程池闲置后，不会保留任何线程。
• 最大线程数为最大整数，意味着如果需要，线程数量可以变得非常大。
• 缓存线程池的保活时间是60秒，线程不会立即被销毁，空闲60内如果有新任务，可以直接复用空闲线程。
• 提交给线程池的线程会放到一个SynchronousQueue的实例中。

## 3 再深一层——从AbstractExecutorService到ThreadPoolExecutor

### 3.2 开始执行任务——execute

• 如果任务能够顺利加入工作队列（true），那么会有工作线程去处理它。典型的工作队列LinkedBlockingQueue就属于这一类，这种情况下，线程数量不会超过corePoolSize的核心线程数。
• 当然，因为避免用重型锁，这里采用了CAS锁的形式，来避免加入任务后，线程池关闭、零线程的情况。
• 如果第二次检查发现线程池不运行了，就移除刚刚加入的任务，并rejectreject方法会进一步调用RejectedExecutionHandler实例的handler.rejectedExecution(command, this);方法以便处理这种任务被线程池拒绝的情况）；
• 如果线程池还在运行，但是没有工作线程，就新建一个线程来处理工作队列中新加入的任务。
• 如果任务不能顺利加入工作队列（false），那么就需要启动新的工作线程。典型的工作队列SynchronousQueue就属于这一类，如果没有线程阻塞在读取上，就无法插入新的任务，即会返回false。这么一来，就会启动新的线程，毕竟有阻塞在读取上的线程，才能加入新的任务。这意味着线程数量完全有可能超过corePoolSize规定的核心线程数。

### 3.3 工作队列——BlockingQueue

ThreadPoolExecutor中，工作队列workQueue是一个BlockingQueue<Runnable>

### 3.6 从工作队列中取任务——getTask

ThreadPoolExecutor.getTask()的实现：

• 如果timed==true，则在主循环中限时等待提取工作队列中的任务，即workQueue.poll方法：
• 如果工作队列中有任务，则立即返回；
• 如果没有，则等待指定时间，如果仍然没有，则返回null
• （Retrieves and removes the head of this queue, waiting up to the specified wait time if necessary for an element to become available.）
• 如果timed==false，则在主循环中阻塞式提取工作队列中任务，即workQueue.take方法：
• 如果工作队列中有任务，则立即返回；
• 如果没有，则线程阻塞，直到生产者加入任务后，有任务实例再返回。

## 4 J.U.C阻塞队列

### 4.1 无容量的同步队列——SynchronousQueue

A blocking queue in which each insert operation must wait for a corresponding remove operation by another thread, and vice versa. A synchronous queue does not have any internal capacity, not even a capacity of one. You cannot peek at a synchronous queue because an element is only present when you try to remove it; you cannot insert an element (using any method) unless another thread is trying to remove it; you cannot iterate as there is nothing to iterate. The head of the queue is the element that the first queued inserting thread is trying to add to the queue; if there is no such queued thread then no element is available for removal and poll() will return null. For purposes of other Collection methods (for example contains), a SynchronousQueue acts as an empty collection. This queue does not permit null elements.

### 4.2 链表阻塞队列——LinkedBlockingQueue

An optionally-bounded blocking queue based on linked nodes. This queue orders elements FIFO (first-in-first-out). The head of the queue is that element that has been on the queue the longest time. The tail of the queue is that element that has been on the queue the shortest time. New elements are inserted at the tail of the queue, and the queue retrieval operations obtain elements at the head of the queue. Linked queues typically have higher throughput than array-based queues but less predictable performance in most concurrent applications.

### 4.3 数组阻塞队列——ArrayBlockingQueue

A bounded blocking queue backed by an array. This queue orders elements FIFO (first-in-first-out). The head of the queue is that element that has been on the queue the longest time. The tail of the queue is that element that has been on the queue the shortest time. New elements are inserted at the tail of the queue, and the queue retrieval operations obtain elements at the head of the queue. This is a classic "bounded buffer", in which a fixed-sized array holds elements inserted by producers and extracted by consumers. Once created, the capacity cannot be changed. Attempts to put an element into a full queue will result in the operation blocking; attempts to take an element from an empty queue will similarly block.

This class supports an optional fairness policy for ordering waiting producer and consumer threads. By default, this ordering is not guaranteed. However, a queue constructed with fairness set to true grants threads access in FIFO order. Fairness generally decreases throughput but reduces variability and avoids starvation.