vlambda博客
学习文章列表

线程池的任务调度流程

问题:

1、线程池的启动策略?
2、线程池的任务调度流程?
3、线程池的工作原理?
4、如果你提交任务时,线程池队列已满,这时会发生什么?

/**
* 使用标准构造器构造一个普通的线程池
*
* @param corePoolSize 核心线程数,即使线程空闲,也不会回收
* @param maximumPoolSize 线程数的上限(最大线程数)
* @param keepAliveTime 线程最大空闲时间(线程的生存时间)
* @param unit 时间单位
* @param workQueue 任务的排队队列
* @param threadFactory 新线程的产生方式
* @param handler 拒绝策略
*/

public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)

线程池的任务调度流程大致如下:

(1)如果当前工作线程数量小于核心线程数量,执行器总是优先创建一个任务线程,而不是从线程队列中获取一个空闲线程。

(2)如果线程池中总的任务数量大于核心线程池数量,新接收的任务将被加入阻塞队列中,一直到阻塞队列已满。在核心线程池数量已经用完、阻塞队列没有满的场景下,线程池不会为新任务创建一个新线程。

(3)当完成一个任务的执行时,执行器总是优先从阻塞队列中获取下一个任务,并开始执行,一直到阻塞队列为空,其中所有的缓存任务被取光。

(4)在核心线程池数量已经用完、阻塞队列也已经满了的场景下,如果线程池接收到新的任务,将会为新任务创建一个线程(非核心线程),并且立即开始执行新任务。
(5)在核心线程都用完、阻塞队列已满的情况下,一直会创建新线程去执行新任务,直到池内的线程总数超出maximumPoolSize。如果线程池的线程总数超过maximumPoolSize,线程池就会拒绝接收任务,当新任务过来时,会为新任务执行拒绝策略。

在创建线程池时,如果线程池的参数(如核心线程数量、最大线程数量、BlockingQueue等)配置得不合理,就会出现任务不能被正常调度的问题。

比如corePoolSize为1,阻塞队列的大小为100,按照线程创建的规则,需要等阻塞队列已满,才会去创建新的线程。假如加入了5个任务,阻塞队列大小为4(<100),所以线程池的调度器不会去创建新的线程,后面的4个任务只能等待。

(1)核心和最大线程数量、BlockingQueue队列等参数如果配置得不合理,可能会造成异步任务得不到预期的并发执行,造成严重的排队等待现象。

(2)线程池的调度器创建线程的一条重要的规则是:在corePoolSize已满之后,还需要等阻塞队列已满,才会去创建新的线程。

 

--end--