ThreadPoolExecutor类的讲解
ThreadPoolExecutor类的讲解
参考文档地址1: 全网最详细的线程池 ThreadPoolExecutor 解读
1 线程池状态
五种状态:
线程池的状态 | 说明 |
---|---|
running | 允许提交并处理任务 |
shutdown | 不允许提交新的任务,但是会处理已提交的任务 |
stop | 不允许提交任务,也不会处理阻塞队列中的未执行任务,并设置正在执行的线程的中断标志位 |
tidying | 所有任务执行完毕,池中工作的线程数为0,等待执行terminated()勾子方法 |
terminated | terminated()勾子方法执行完毕 |
-
线程池的
shutdown()
方法,将线程池有running(运行状态)变为shutdown状态 -
线程池的
shutdownNow()
方法,将线程池由running或shutdown状态转化为stop状态
注: shutdown状态和stop状态 先回转变为tidying状态,最终都会变为terminated
2 ThreadPoolExecutor构造函数:
ThreadPoolExecutor继承自AbstractExecutorService,而AbstractExecutorService实现了ExecutorService接口
3 线程池的核心参数
-
corePoolSize 核心线程池的大小
-
maximumPoolSize 线程池最多能创建的线程数
-
workQueue 阻塞队列,用于保存任务的阻塞队列
-
keepAliveTime 空闲线程存活时间
-
unit 时间单位
-
threadFactory: 创建线程工的工程类
-
handler 饱和策略(拒绝策略)
keepAliveTime
当一个线程无事可做,超过一定的时间keepAliveTime时,线程池会判断,如果当前运行的线程数大于corePoolSize,那么这个线程就被停掉;所以线程吃的所有任务完成后,他最终会收缩到corePoolSize的大小
注:如果线程池设置了
allowCoreThreadTimeout
参数为true(默认false),那么当空闲线程超过keepaliveTime
后直接停掉。(不会判断线程数是否大于corePoolSize
)即:最终线程数会变为0
workQueue:它决定了缓存任务的排队策略
ThreadPoolExecutor线程池推荐了三种等待队列,它们是:SynchronousQueue,LinkedBlockingQueue和ArrayBlockingQueue
有界队列
-
SynchronousQueue:一个不存储元素的阻塞队列
-
ArrayBlockingQueue:一个由数组支持的有界阻塞队列
无界队列
实际上任何无限容量的队列/栈都是有容量的,这个容量就是Integer.MAX_VALUE
-
LinkedBlockQueue:
基于链表结构的无界队列; -
PriorityBlockingQueue
:是一个按照优先级进行内部元素排序的无界阻塞队列
如果
BlockingQueue
是无界的,那么永远不会触发maximumPoolSize
,自然keepAliveTime
也就没有了意义。
4 线程池的工作原理
当调用线程池的executor()方法添加一个任务时,线程池会做如下判断:
-
如果有空闲线程,则直接执行该任务;
-
如果没有空闲线程,且当前运行的线程数少于corePoolSize,则创建新的线程执行该任务;
-
如果没有空闲线程,且当前线程等于corePoolSize,同时阻塞队列未满,则将任务加入队列,而不添加新的线程;
-
如果没有空闲线程,且阻塞队列已满,同时池中的线程数少于maximumPoolSize,则创建新的线程执行该任务;
-
如果没有空闲线程,且阻塞队列已满,同时池中的线程数等于maximumPoolSize,则根据构造函数中的handler指定的策略来拒绝新的任务
5 handler拒绝策略
策略 | 描述 |
---|---|
AbortPolicy() | 抛出异常,由开发人员进行处理,默认策略 |
CallerRunsPolicy() | 由向线程池提交任务的线程来执行该任务 |
DiscardPolicy | 抛弃当前的任务 |
DiscardOldestPolicy() | 抛弃最旧的任务 |
最科学的的还是 AbortPolicy 提供的处理方式
6 常用的方法
除了在创建线程池时指定上述参数的值外,还可在线程池创建以后通过如下方法进行设置。
此外,还有一些方法:
-
getCorePoolSize()
:返回线程池的核心线程数,这个值是一直不变的,返回在构造函数中设置的coreSize大小; -
getMaximumPoolSize()
:返回线程池的最大线程数,这个值是一直不变的,返回在构造函数中设置的coreSize大小; -
getLargestPoolSize()
:记录了曾经出现的最大线程个数(水位线); -
getPoolSize()
:线程池中当前线程的数量; -
getActiveCount()
:Returns the approximate(近似) number of threads that are actively executing tasks; -
prestartAllCoreThreads()
:会启动所有核心线程,无论是否有待执行的任务,线程池都会创建新的线程,直到池中线程数量达到 corePoolSize; -
prestartCoreThread()
:会启动一个核心线程(同上); -
allowCoreThreadTimeOut(true)
:允许核心线程在KeepAliveTime时间后,退出;
7 Executors类:
Executors类的底层实现便是ThreadPoolExecutor!Executors 工厂方法有:
-
Executors.newCachedThreadPool()
:无界线程池,可以进行自动线程回收 -
Executors.newFixedThreadPool(int)
:固定大小线程池 -
Executors.newSingleThreadExecutor()
:单个后台线程