JUC源码解析(2)----线程池之 newFixedThreadPool()

JDK 为我们内置了四种常见线程池的实现,均可以使用 Executors 工厂类创建。

1.newFixedThreadPool

《JUC源码解析(2)----线程池之 newFixedThreadPool()》

《JUC源码解析(2)----线程池之 newFixedThreadPool()》

上面这两个方法是创建固定数量的线程池的两种方法,两者的区别是:第二种创建方法多了一个线程工厂的方法。我们继续看ThreadPoolExecutor这个类中的构造函数:

《JUC源码解析(2)----线程池之 newFixedThreadPool()》

《JUC源码解析(2)----线程池之 newFixedThreadPool()》

FixedThreadPool 被称为可重用固定线程数的线程池。

        当线程池中的线程数大于corePoolSize 时,keepAliveTime 为多余的空闲线程等待新任务的最长时间,超过这个时间后多余的线程将被终止。把 keepAliveTime 设置为0L,意味着多余的空闲线程会被立即终止。

我们再说一下线程的管理过程:

首先创建一个线程池,然后根据任务的数量逐步将线程增大到corePoolSize,如果此时仍有任务增加,则放置到workQueue中,直到workQueue爆满为止,然后继续增加池中的线程数量(增强处理能力),最终达到maxinumPoolSize。那如果此时还有任务要增加进来呢?这就需要handler来处理了,或者丢弃新任务,或者拒绝新任务,或者挤占已有的任务。在任务队列和线程池都饱和的情况下,一旦有线程处于等待(任务处理完毕,没有新任务)状态的时间超过keepAliveTime,则该线程终止,也就是说池中的线程数量会逐渐降低,直至为corePoolSize数量为止。

在《编写高质量代码 改善Java程序的151个建议》这本书里举的这个例子很形象:

《JUC源码解析(2)----线程池之 newFixedThreadPool()》《JUC源码解析(2)----线程池之 newFixedThreadPool()》

 

可以看到,FixedThreadPool 的核心线程数和最大线程数都是指定值,也就是说当线程池中的线程数超过核心线程数后,任务都会被放到阻塞队列中。

此外 keepAliveTime 为 0,也就是多余的空余线程会被立即终止(由于这里没有多余线程,这个参数也没什么意义了)。

而这里选用的阻塞队列是 LinkedBlockingQueue,使用的是默认容量 Integer.MAX_VALUE,相当于没有上限。

因此这个线程池执行任务的流程如下:

  1. 线程数少于核心线程数,也就是设置的线程数时,新建线程执行任务
  2. 线程数等于核心线程数后,将任务加入阻塞队列 
    • 由于队列容量非常大,可以一直加加加
  3. 执行完任务的线程反复去队列中取任务执行

FixedThreadPool 用于负载比较重的服务器,为了资源的合理利用,需要限制当前线程数量。

    原文作者:JUC
    原文地址: https://blog.csdn.net/qingtian211/article/details/81867314
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞