【JUC】线程池-ThreadPoolExecutor源码解析
1.线程池能做什么?
- 控制运行线程的数量
- 将任务交给线程池,然后线程负责创建和启动这些线程
- 如果要执行的任务数超过了线程池设置的最大线程数,就让超出部分排队等候
- 然后等其他线程执行完毕,再从队列中取出任务来执行.
- 简单来说,线程池可以管理线程,进行线程复用和控制最大并发数。
2.线程池优点?
-
第一:降低资源消耗.通过线程复用降低线程创建和销毁造成的消耗.
-
第二: 提高响应速度.当任务到达时,任务可以不需要等到线程创建就能立即执行。
-
第三:提高线程的可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。
3.JUC中线程池如何实现?
- idea找到JUC包里面的Executor,右键如图:
- 最上层的接口Executor只定义了一个方法:
public interface Executor {
//Runnable 实现类作为入参,提交给线程池,由线程池创建线程并启动。
void execute(Runnable command);
}
- 接下来是ExecutorService接口,它继承于Executor接口,增加了一些方法,具体如下:
public interface ExecutorService extends Executor {
//关闭线程池
void shutdown();
//关闭线程池
List<Runnable> shutdownNow();
//线程池是否关闭
boolean isShutdown();
//callable实现类作为入参,有返回值
<T> Future<T> submit(Callable<T> task);
//Runnable 实现类作为入参,底层是将Runnbale和结果组合成一个Callable,所以有返回值
<T> Future<T> submit(Runnable task, T result);
//批量提交任务
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
。。。。
}
-
再下面是AbstractExecutorService抽象类,它实现了ExecutorService接口,并对其中一些方法做了实现。
-
还有ScheduledExecutorService接口,它继承了ExecutorService接口,并且添加了一些带延时时间作为参数的方法。
-
最后,主角ThreadPoolExecutor出场:
4.ThreadPoolExecutor源码分析
- ThreadPoolExecutor构造函数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
//主要看入参,内容就省略了
}
- 入参含义:
1,corePoolSize:核心线程数量,在创建了线程池后,当有请求任务来之后,就会安排池中的线程去执行。
2,maximumPoolSize:最大线程数,线程池能容纳同时执行的最大线程数,此值大于1
3, keepAliveTime:多余的空闲线程存活时间,当线程数大于核心线程数小于最大线程数时,比核心线程多出来的线程在空闲时间达到keepAliveTime值时,会被销毁直到只剩下corePoolSize个线程为止。
4,unit:keepAliveTime的单位,毫秒,秒,分钟。。。。
5,workQueue,任务队列,被提交,但未被执行的任务
6, threadFactory:生成线程池中工作线程的线程工厂,用于创建新的线程,一般用默认即可
7,handler:拒绝策略,当线程池满了,无法再接收任务时的拒绝策略。
4.1 线程池底层原理
- 开撸更多ThreadPoolExecutor源码前,我们先来看看线程池的执行流程,这个东西有助于我们理解源码:
4.1.1 主要流程:
- 主线程提交任务到线程池。
- 线程池执行任务,先看看核心线程有没有满,没满就从核心线程中找出一个空闲线程复用,来执行任务。
- 然后核心线程已经满了,就看看任务队列有没有满,没满就加入任务队列,等待执行。
- 如果任务队列也满了,就看线程数有没有到最大线程数,没有的话,就创建新的线程,开始执行任务。
- 如果任务队列满了,线程数也到最大线程数了,那就执行拒绝策略,不再接受任务。
4.1.2 图解:
4.2 开撸源码
- ThreadPoolExecutor必要的成员变量介绍
//保存运行状态和线程池中有效线程的数量,高三位表示线程池的运行状态 (runState) 和低29位表示线程池内有效线程的数量 (workerCount)
private final AtomicInteger ctl