线程池

  1. 执行流程
  2. 拒绝策略

在 Java 中的线程池中,在核心线程数已满的情况下,为什么要先判断等待队列是否已满,未满放到队列中。而不是先判断最大线程数是否已满? 线程池的目的应该尽可能创建多个线程。

原因有很多,可能等待队列充当了个缓存区,允许系统在流量高峰时有更多弹性,避免不必要的资源消耗。

另外,在 https://zhuanlan.zhihu.com/p/92632090 中也提到了这点,每当需要创建线程时,都会调用 addWorker() 方法,在这个方法中需要获取锁,而多个线程获取锁会造成资源的争抢。如果在最大线程数未满的情况下,直接创建新的线程,这样每次都需要多获取一次锁。

执行流程

1.提交任务后会首先进行当前工作线程数与核心线程数的比较,如果当前工作线程数小于核心线程数,则直接调用 addWorker() 方法创建一个核心线程去执行任务;

2.如果工作线程数大于核心线程数,即线程池核心线程数已满,则新任务会被添加到阻塞队列中等待执行,当然,添加队列之前也会进行队列是否为空的判断;

3.如果线程池里面存活的线程数已经等于核心线程数了,且阻塞队列已经满了,再会去判断当前线程数是否已经达到最大线程数 maximumPoolSize,如果没有达到,则会调用 addWorker() 方法创建一个非核心线程去执行任务;

4.如果当前线程的数量已经达到了最大线程数时,当有新的任务提交过来时,会执行拒绝策略

拒绝策略

AbortPolicy:丢弃任务并抛出异常。

DiscardPolicy:直接丢弃,不抛出异常。

DiscardOldestPolicy:丢弃队列最前面的任务。

CallerRunsPolicy:哪个线程提交的任务,哪个线程复制执行,也不丢弃。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1216271933@qq.com

×

喜欢就点赞,疼爱就打赏