前两篇我们说了一下线程的前置的基础知识,多线程中还有一些面试中必问必考并且日常开发中会用到的知识那就是JUC包下的线程池,本篇文章我们来梳理一下线程池体系的一些内容。
首先我们先了解一下
1.常用的线程池体系图:(通过idea查看类继承和实现的关系图)
备注:绿色虚线部分是类实现接口的方法,绿色实现是接口继承接口,蓝色实现是类继承类的方法
Executor:线程池顶级接口。
ExecutorService:线程池次级接口,对Executor接口做了一些拓展,增加了一些功能,继承了Executor接口
ScheduledExecutorService:对ExecutorService做了一些拓展,增加了一些定时任务相关的功能。
AbstractExecutorService:抽象类,运用模板方法设计模式实现了一些方法。
ThreadPoolExecutor:基本的线程池类,包含最基本的一些线程池操作的方法实现。
ScheduledThreadPoolExecutor:定时任务线程池,用于实现定时任务相关功能。
Executors:线程池工具类,定义了一些快速实现线程池的方法。
**特别声明:**阿里的 Java开发手册,上面有线程池的一个建议:
【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,
这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
2.ThreadPoolExecutor
既然阿里的java开发手册都发话了那么我们也要按照开发手册严格要求自己,我们就来说一些面试和实际开发中用到的ThreadPoolExecutor,来上才艺~~
从上面源码可以看到,ThreadPoolExecutor方法中有7个参数,下面来分别解释一下每个参数的含义,这些参数关系到线程池执行过程。
corePoolSize:线程池的核心线程数。
maximumPoolSize:线程池中最大线程数。
keepAliveTime:当前线程池数量超过 corePoolSize 时,多余的空闲线程的存活时间,即多
次时间内会被销毁
unit:存活时间的基本单位。
workQueue:工作队列,或者说是阻塞等待队列。
threadFactory:线程池工厂。
hander:拒绝策略,当任务太多来不及处理,如何拒绝任务。
RejectedExecutionHandler(拒绝策略顶级接口)跟随源码我们可以发现有4种拒绝策略:
- DiscardPolicy : 该策略默默地丢弃无法处理的任务,不予任何处理。
- DiscardOldestPolicy : 丢弃最老的一个请求,也就是即将被执行的一个任务,并尝试再 次提交当前任务。
- CallerRunsPolicy : 只要线程池未关闭,该策略直接在调用者线程中,运行当前被丢弃的 任务。
- AbortPolicy : 直接抛出异常,阻止系统正常运行。
说完线程池我们来说一下线程池的执行顺序。
3.普通线程池执行顺序
- 当线程数小于核心线程数时,创建线程
- 当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列
- 当线程数大于等于核心线程数,且任务队列已满时
①若线程数小于最大线程数时,创建线程
②若线程数等于最大线程数时,调用拒绝策略