线程池任务调度:新建线程处理阻塞队列溢出任务还是最早任务?

问题引出

在学习线程池基本工作原理的时候产生一个疑问:当线程池中核心线程都被占用,且阻塞队列已满时,再有新任务会触发线程的新建。那么,新建的线程执行的任务是从阻塞队列中取出最早进入的任务,还是直接执行刚刚新进来无法放入队列的任务呢?

带着这个疑问,阅读ThreadPoolExecutor的源码,最终得到问题的答案。


首先,简单介绍一下线程池基本工作原理及工作流程。

线程池基本工作原理

以ThreadPoolExecutor为例,新建一个线程池有七大参数:

* corePoolSize 核心线程数。指线程池中维护一个最小的线程数量。线程池新建的时候便会往池中添加核心线程数个线程,之后即使这些线程处于空闲状态,也不会被销毁。除非设置了核心线程超时时间(allowCoreThreadTimeOut)。

* maximumPoolSize 最大线程数。当线程池中线程不足以满足需求时(后续会在工作流程中详细介绍),线程池会创建新线程。但是创建新线程后的总线程数受到maximumPoolSize最大线程数量的限制。

* keepAliveTime 存活时间。如果当前运行线程数大于核心线程数,空闲线程在等待了 keepAliveTime的时间后仍然没有接收到新任务,则会销毁该空闲线程。

* unit keepAliveTime参数的时间单位。

* workQueue 阻塞队列。当线程池所有的线程都不处于空闲状态,新接收到的任务会存入阻塞队列;若阻塞队列已满无法存入,则会创建新线程;若当前线程数已经超出最大线程数,则会执行拒绝策略。

* threadFactory 线程创建工厂。指创建一个新线程时使用的工厂,可以进行自定义设置,比如添加自定义线程名等功能。

* handler 拒绝策略。按照指定的拒绝策略拒绝执行任务。

线程池基本工作流程

* 1.创建线程池,准备核心线程数corePoolSize大小的核心线程

* 2.若当前线程池中的线程都被占用,此时再进来任务将被放入阻塞队列中。当线程池中的线程完成其任务转为空闲状态时,会从阻塞队列中获取任务执行。

* 3.若当前线程池中的线程都被占用,阻塞队列也满了,此时线程池会直接创建新线程。但是最大线程数只能开到maximumPoolSize;若当前线程数大于核心线程数,当有线程处于空闲状态超过存活时间keepAliveTime,则会销毁该空闲线程 

* 4.若当前线程池中的线程都被占用,阻塞队列也满了,当前线程数也已经达到maximumPoolSize,此时仍然有新任务进来,则会使用handler指定的拒绝策略处理新进来的任务。

图片摘自:线程池的执行流程_线程池执行流程-CSDN博客


源码阅读

了解完线程池的基本工作流程后,回归到文章开头提到的问题,新建的线程执行的任务是从阻塞队列中取出最早进入的任务,还是直接执行刚刚新进来无法放入队列的任务呢?

1.当有一个新任务command出现时,会调用execute()方法。

从源码中不难发现,当阻塞队列未满的时候,会新建一个firstTask为null的线程;而当阻塞队列已满,会导致队列添加不成功,则会调用addWorker(command,false)新建一个firstTask为command的线程。

2.那么,新建的线程是如何运行的呢?

从源码中我们可以发现,若线程有设置firstTask,会直接执行firstTask所指定的任务,并将firstTask置空;由于执行任务是一个while循环,在此之后该线程会调用getTask()方法一直从线程池中取出任务,直至getTask()返回值为null,销毁该线程。

3.getTask()中还有一个有意思的细节。

存活时间通过此段代码来实现。当开启了存活时间,则会使用poll(long timeout, TimeUnit unit)从阻塞队列中获取任务。即:若阻塞队列为空,也要等待keepAliveTime指定的时间,如果依然为空才返回null。也就是就算阻塞队列为空,线程为空闲状态,也需要等待keepAliveTime才会将其销毁

结论:线程的一生

综上,当线程池中核心线程都被占用,且阻塞队列已满时,再有新任务会新建一个线程并直接执行该新进来的任务。当该任务执行完毕,这个新建的线程会不断从阻塞队列池取出任务来执行,直至阻塞队列持续为空达到keepAliveTime的时间且当前线程数大于核心线程数时,该线程被销毁。

  • 40
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值