目录
线程池概念
线程池是一种利用池化技术思想来实现的线程管理技术,主要是为了复用线程、便利地管理线程和任务、并将线程的创建和任务的执行解耦开来。我们可以创建线程池来复用已经创建的线程来降低频繁创建和销毁线程所带来的资源消耗。在JAVA中主要是使用ThreadPoolExecutor类来创建线程池,并且JDK中也提供了Executors工厂类来创建线程池
为什么要用线程池?
先看看创建线程执行任务的模型,如下图所示
从上图我们可以看得出来创建线程的一些缺点:
- 不受控制风险,对于每个创建的线程没有统一管理的地方,每个线程创建后我们不知道线程的去向
- 每执行一个任务都需要创建新的线程来执行,创建线程对系统来说非常得浪费资源
线程池的优点
线程池的优点就在于:
- 降低资源消耗,复用已创建的线程来降低创建和销毁线程的消耗。
- 提高响应速度,任务到达时,可以不需要等待线程的创建立即执行。
- 提高线程的可管理性,使用线程池能够统一的分配、调优和监控。
JAVA线程池概述
Java中线程池的核心实现类是ThreadPoolExecutor,可以通过该类地构造方法来构造一个线程池,我们先来看下ThreadPoolExecutor的整个继承体系
- Executor接口提供了将任务的执行和线程的创建以及使用解耦开来的抽象
- ExecutorService接口继承了Executor接口,在Executor的基础上,增加了一些关于管理线程池本身的一些方法,比如查看任务的状态、stop/terminal线程池、获取线程池的状态等等。
ThreadPoolExecutor的构造组成
- corePoolSize,核心线程数量,决定是否创建新的线程来处理到来的任务
- maximumPoolSize,最大线程数量,线程池中允许创建线程地最大数量
- keepAliveTime,线程空闲时存活的时间
- unit,空闲存活时间单位
- workQueue,任务队列,用于存放已提交的任务
- threadFactory,线程工厂,用于创建线程执行任务
- handler,拒绝策略,当线程池处于饱和时,使用某种策略来拒绝任务提交
public ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler
)
线程池的生命周期
线程池五种状态
线程池生命周期流转
ThreadPoolExecutor中表示线程池状态设计
在ThreadPoolExecutor中使用一个AtomicInteger类型的ctl字段来描述线程池地运行状态和线程数量,通过ctl的高三位来表示线程池的5种状态,低29位表示线程池中现有的线程数量。使用最少的变量来减少锁竞争,提高并发效率。
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
// 线程池线程数地bit数
private static final int COUNT_BITS = Integer.SIZE - 3;
// 线程池中最大线程容量
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// runState is stored in the high-order bits
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;
// 获取线程池地运行状态
private static int runStateOf(int c) { return c & ~CAPACITY; }
// 获取有效工作线程地数量
private static int workerCountOf(int c) { return c & CAPACITY; }
// 组装线程数量和线程池状态
private static int ctlOf(int rs, int wc) { return rs | wc; }
2.3 线程池地执行流程
- 如果workerCount < corePoolSize ==> 创建线程执行提交的任务
- 如果workerCount >= corePoolSize && 阻塞队列未满 ==> 添加至阻塞队列,等待后续线程来执行提交地任务
- 如果workerCount >= corePoolSize && workerCount < maxinumPoolSize && 阻塞队列已满 ==> 创建非核心线程执行提交的任务
- 如果workerCount >= maxinumPoolSize && 阻塞队列已满 ==> 执行拒绝策略