Java ThreadPoolExecutor 类参数讲解

Java ThreadPoolExecutor

@author:Jingdai
@date:2020.11.03

最近看《Java并发编程实战》这本书,书中经常出现 ThreadPoolExecutor ,而自己对这个类不是很熟悉,学习了一下,简要总结一下。

基本概念

ThreadPoolExecutor 这个类是一个线程池,之前看《 Java核心技术·卷1》这本书,里面有介绍可以用 Executors 类中的静态方法创建线程池,比如 Executors.newCachedThreadPool() 方法,其实它本质也是调用ThreadPoolExecutor 的构造方法来创建线程池的,后面会介绍。但是看了Alibaba的Java开发手册,不允许使用 Executors 类来创建线程池,如图。

在这里插入图片描述

所以还是非常有必要学习一下 ThreadPoolExecutor 类的使用的。

构造函数参数

ThreadPoolExecutor 类有4个构造方法来创建线程池。分别如下:

  • ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue)
  • ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, RejectedExecutionHandler handler)
  • ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory)
  • ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)

现分别对各个参数进行简要介绍,这里先介绍 corePoolSizemaximumPoolSizeworkQueue 三个参数,因为他们是相互关联的。

corePoolSize :线程池的核心线程数
maximumPoolSize :线程池的最大线程数
workQueue :线程池使用的阻塞队列,这里主要关注它的长度

首先假设 corePoolSizemaximumPoolSizeworkQueue 的长度都是一个大于 0 的整数。在一个新的任务 task 到来时, 分4种情况,如下图。

在这里插入图片描述

  1. 当线程池中线程数 < corePoolSize ,那么就创建一个新的核心线程,并将任务交给它去执行。
  2. 当线程池中线程数 >= corePoolSize ,并且阻塞队列 workQueue 没有满,则将新的任务放入阻塞队列中去等待。
  3. 当线程池中线程数 >= corePoolSize 且线程池中线程数 < maximumPoolSize,同时阻塞队列 workQueue 已经满了,则将创建一个新的非核心线程,并将任务交给它去执行。
  4. 当线程池中线程数 = maximumPoolSize,同时阻塞队列 workQueue 已经满了,则该任务会被拒绝,具体的拒绝处理方式稍后会介绍。

注意:当设置的阻塞队列 workQueue 是无限队列时(如没有预定义容量的LinkedBlockingQueue),则 maximumPoolSize 将没有用处。因为当超过 corePoolSize 时,任务总会加到阻塞队列中,而阻塞队列不会满,所以永远不会创建非核心线程。

keepAliveTime :线程保持活跃时间
unit :线程保持活跃时间的单位

如果线程池中的线程数量超过 corePoolSize ,则当多余的线程空闲时间超过上面参数设置的时间时,它将会被销毁。默认情况下,仅当线程池中线程数超过 corePoolSize 时,这个策略才会执行,但是可以通过allowCoreThreadTimeOut(boolean) 方法来设置该策略对核心线程同样适用。

handler :拒绝任务处理器

当线程池关闭或线程池容量满了(workQueue 满且池中线程数为 maximumPoolSize)时,再向线程池中提交任务时,将会引发拒绝任务处理器工作。有4种预定义的拒绝处理器。

  1. ThreadPoolExecutor.AbortPolicy :默认的拒绝处理器,当拒绝任务时抛出一个 RejectedExecutionException 异常。
  2. ThreadPoolExecutor.CallerRunsPolicy :让提交任务的线程自己去执行提交的任务。比如main线程给线程池提交一个任务被线程池拒绝了,则main线程自己执行这个任务。
  3. ThreadPoolExecutor.DiscardPolicy :直接丢弃无法执行的任务。
  4. ThreadPoolExecutor.DiscardOldestPolicy :如果线程池没有关闭,丢弃线程池中阻塞队列 workQueue 的第一个任务,然后重新尝试执行。

其他相关方法

上面介绍的是构造函数的相关参数,同时,在线程池创建完成后,相关参数也是可以改变的。

  • getCorePoolSize()setCorePoolSize(int corePoolSize)

    从名字可以看出,可以查看和修改线程池的核心线程数

  • getMaximumPoolSize()setMaximumPoolSize(int maximumPoolSize)

    查看和修改线程池最大的线程数

  • setKeepAliveTime(long time, TimeUnit unit)

    设置线程多长时间不活跃就会被销毁

其他

上面提到 Executors 的静态方法创建线程池其本质也是调用了 ThreadPoolExecutor 的构造方法,看一下 jdk8 的源码。

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

这里会发现其本质都是这样,所以通过这个构造方法创建线程池可以更加清楚的知道线程池的各个参数。

参考

  • Java 8 API
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值