7000字+24张图带你彻底弄懂线程池(二)

发布于 2022-6-17 16:51
浏览
0收藏

 

当任务执行完之后,线程不会退出,而是会去从阻塞队列中获取任务,如下图

7000字+24张图带你彻底弄懂线程池(二)-开源基础软件社区

接下来如果又提交了一个任务,也会按照上述的步骤,去判断是否小于核心线程数,如果小于,还是会创建线程来执行任务,执行完之后也会从阻塞队列中获取任务。这里有个细节,就是提交任务的时候,就算有线程池里的线程从阻塞队列中获取不到任务,如果线程池里的线程数还是小于核心线程数,那么依然会继续创建线程,而不是复用已有的线程。

 

如果线程池里的线程数不再小于核心线程数呢?那么此时就会尝试将任务放入阻塞队列中,入队成功之后,如图

7000字+24张图带你彻底弄懂线程池(二)-开源基础软件社区

这样在阻塞的线程就可以获取到任务了。

 

但是,随着任务越来越多,队列已经满了,任务放入失败了,那怎么办呢?

 

此时就会判断当前线程池里的线程数是否小于最大线程数,也就是入参时的maximumPoolSize参数

 

如果小于最大线程数,那么也会创建非核心线程来执行提交的任务,如图

7000字+24张图带你彻底弄懂线程池(二)-开源基础软件社区

所以,从这里可以发现,就算队列中有任务,新创建的线程还是优先处理这个提交的任务,而不是从队列中获取已有的任务执行,从这可以看出,先提交的任务不一定先执行。

 

但是不幸的事发生了,线程数已经达到了最大线程数量,那么此时会怎么办呢?

 

此时就会执行拒绝策略,也就是构造线程池的时候,传入的RejectedExecutionHandler对象,来处理这个任务。

7000字+24张图带你彻底弄懂线程池(二)-开源基础软件社区

RejectedExecutionHandler的实现JDK自带的默认有4种

  • AbortPolicy:丢弃任务,抛出运行时异常
  • CallerRunsPolicy:由提交任务的线程来执行任务
  • DiscardPolicy:丢弃这个任务,但是不抛异常
  • DiscardOldestPolicy:从队列中剔除最先进入队列的任务,然后再次提交任务

 

线程池创建的时候,如果不指定拒绝策略就默认是AbortPolicy策略。当然,你也可以自己实现RejectedExecutionHandler接口,比如将任务存在数据库或者缓存中,这样就数据库或者缓存中获取到被拒绝掉的任务了。

 

到这里,我们发现,线程池构造的几个参数corePoolSize、maximumPoolSize、workQueue、threadFactory、handler我们都在上述的执行过程中讲到了,那么还差两个参数keepAliveTime和unit(unit是keepAliveTime的时间单位)没讲到,所以keepAliveTime是如何起到作用的呢,这个问题留到后面分析。

 

文章转自公众号:三友的java日记

标签
已于2022-6-17 16:51:00修改
收藏
回复
举报
回复
添加资源
添加资源将有机会获得更多曝光,你也可以直接关联已上传资源 去关联
    相关推荐