并发篇之线程池
- 1、线程池的基本原理
- 2、为什么要使用线程池(线程池的优点)
- 3、线程池的执行流程
- 4、线程池的核心参数
- 5、线程池的创建
- 6、线程池的关闭(`shutdown`和`shutdownNow`)
- 7、线程池的状态
- 8、线程池饱和策略(拒绝策略)
- 9、线程池的工作队列
- 10、线程池异常处理
- 11、常用线程池
- 12、如何合理的配置线程池
- 13、实现Runnable接口和Callable接口的区别(如何拿到线程池返回值)
- 14、执行execute()方法和submit()方法的区别
- 15、prestartCoreThread()方法和prestartAllCoreThreads()方法
- 16、怎么理解无界队列和有界队列
- 17、使用无界队列的线程池会导致内存飙升吗?
- 18、说说几种常见的线程池及使用场景?
- 19、单机上一个线程正在处理服务,如果忽然断电了怎么办(正在处理和阻塞队列里的请求怎么处理)
1、线程池的基本原理
线程池会预先创建一定数量的线程对象,放入到缓冲池中,比如创建了三个线程对象,任务过来之后,要从线程池中取,假如同时来了四个任务,只能执行三个任务,第四个任务需要进入等待队列中排队,等待某个任务执行完毕释放线程后,第四个任务就可以执行了。当同时来了很多个任务,等待队列被排满了,线程池就会创建新的线程对象去执行任务,但线程池的容量是有限的,当线程数达到了线程池的最大容量,这个时候再来任务,线程池就会拒绝任务
2、为什么要使用线程池(线程池的优点)
- 降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的消耗
- 提高响应速度:当任务到达时,任务可以不需要的等到线程创建就能立即执行
- 提高线程的可管理性:线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控
3、线程池的执行流程
- 提交一个任务,线程池里存活的核心线程数小于corePoolSize,线程池会创建一个核心线程去处理提交的任务
- 如果线程池核心线程数已满,即线程数已经等于corePoolSize,一个新提交的任务,会被放进任务队列workQueue排队等待执行‘
- 当线程池里面存活的线程数已经等于corePoolSize,并且任务队列workQueue也满,判断线程数是否达到maximumPoolSize,即最大线程数是否已满,如果没达到,创建一个非核心线程执行提交的任务
- 如果当前的线程数达到了maximumPoolSize还有新的任务过来的话,直接采用拒绝策略处理
4、线程池的核心参数
corePoolSize:
线程池核心线程数maximumPoolSize:
线程池最大线程数keepAliveTime:
线程池中非核心线程空闲的存活时间大小unit:
线程空闲存活时间单位workQueue:
存放任务的阻塞队列threadFactory:
用于设置创建线程的工厂,可以给创建的线程设置有意义的名字,方便排查问题handler:
线程池的饱和策略
5、线程池的创建
《阿里巴巴Java开发手册》中强制线程池不允许使用 Executors 去创建,而是通过ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险
Executors 返回线程池对象的弊端如下:
FixedThreadPool 和 SingleThreadExecutor :允许请求的队列长度为Integer.MAX_VALUE,可能堆积大量的请求,从而导致 OOM。
CachedThreadPool 和ScheduledThreadPool : 允许创建的线程数量为Integer.MAX_VALUE ,可能会创建大量线程,从而导致 OOM。
所以我们创建线程池主要是通过ThreadPoolExecutor类来完成
6、线程池的关闭(shutdown
和shutdownNow
)
关闭线程池,可以通过shutdown
和shutdownNow
这两个方法。它们的原理都是遍历线程池中所有的线程,然后依次中断线程。
shutdown
和shutdownNow
还是有不一样的地方:
shutdownNow
首先将线程池的状态设置为STOP,然后尝试停止所有的正在执行和未执行任务的线程,并返回等待执行任务的列表;shutdown
只是将线程池的状态设置为SHUTDOWN状态,然后中断所有没有正在执行任务的线程
可以看出 shutdown 方法会将正在执行的任务继续执行完,而 shutdownNow 会直接中断正在执行的任务。调用了这两个方法的任意一个,isShutdown方法都会返回 true,当所有的线程都关闭成功,才表示线程池成功关闭,这时调用isTerminated方法才会返回 true。
7、线程池的状态
线程池有这几个状态:
- RUNNING
- SHUTDOWN