关于线程池你不得不知道的一些设置

 更新时间:2024年06月14日 14:27:41   作者:Java科代表  
这篇文章主要介绍了关于线程池你不得不知道的一些设置,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧<BR>

看完我上一篇文章,「你都理解创建线程池的参数吗?」之后,当遇到这种问题,你觉得你完全能够唬住面试官了,50k轻松到手。殊不知,要是面试官此刻给你来个反杀:

初始化线程池时可以预先创建线程吗?线程池的核心线程可以被回收吗?为什么?

如果此刻你一脸懵逼,这个要慌,问题很大,50k马上变5k。

有细心的网友早就想到了这个问题:

在ThreadPoolExecutor线程池中,还有一些不常用的设置。我建议如果您在应用场景中没有特殊的要求,就不需要使用这些设置。

初始化线程池时可以预先创建线程吗?

prestartAllCoreThreads

初始化线程池时是可以预先创建线程的,初始化线程池后,再调用prestartAllCoreThreads()方法,即可预先创建corePoolSize数量的核心线程,我们看源码:

public int prestartAllCoreThreads() {
 int n = 0;
 while (addWorker(null, true))
  ++n;
 return n;
}
private boolean addWorker(Runnable firstTask, boolean core) {
 // ..
}

addWorker方法目的是在线程池中添加任务并执行,如果task为空,线程获取任务执行时调用getTask()方法,该方法从blockingQueue阻塞队列中阻塞获取任务执行,因此线程不会释放,留存在线程池中,如果core=true,说明任务只能利用核心线程来执行。

所以该方法会在线程池总预先创建没有任务执行的线程,数量为corePoolSize。

下面我们测试一下:

从测试结果来看,线程池中已经预先创建了corePoolSize数量的空闲线程。

prestartCoreThread

prestartCoreThread()同样可以预先创建线程,只不过该方法只会与创建1条线程,我们来看源码:

public boolean prestartCoreThread() {
 return workerCountOf(ctl.get()) < corePoolSize &&
  addWorker(null, true);
}

 从方法源码可知,如果此时工作线程数量小于corePoolSize,那么就调用addWorker创建1条空闲核心线程。

下面我们测试一下:

从测试结果来看,线程池中已经预先创建了1条空闲线程。

线程池的核心线程可以被回收吗?

你可能会想到将corePoolSize的数量设置为0,从而线程池的所有线程都是“临时”的,只有keepAliveTime存活时间,你的思路也许时正确的,但你有没有想过一个很严重的后果,corePoolSize=0时,任务需要填满阻塞队列才会创建线程来执行任务,阻塞队列有设置长度还好,如果队列长度无限大呢,你就等着OOM异常吧,所以用这种设置行为并不是我们所需要的。

有没有什么设置可以回收核心线程呢?

allowCoreThreadTimeOut

ThreadPoolExecutor有一个私有成员变量:

private volatile boolean allowCoreThreadTimeOut;

 如果allowCoreThreadTimeOut=true,核心线程在规定时间内会被回收。

上面我也说了,当线程空闲时会从blockingQueue阻塞队列中阻塞获取任务执行,所以我们来看看是保证核心线程不被销毁的,我们直接定位到源码部位:

java.util.concurrent.ThreadPoolExecutor#getTask:

boolean timedOut = false; // Did the last poll() time out?
for (;;) {
 // Are workers subject to culling?
 boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

 try {
  Runnable r = timed ?
   workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
  workQueue.take();
  if (r != null)
   return r;
  timedOut = true;
 } catch (InterruptedException retry) {
  timedOut = false;
 }
}

这里的关键值timed,如果allowCoreThreadTimeOut=true或者此时工作线程大于corePoolSize,timed=true,如果timed=true,会调用poll()方法从阻塞队列中获取任务,否则调用take()方法获取任务。

下面我来解释这两个方法:

  1. poll(long timeout, TimeUnit unit):从BlockingQueue取出一个任务,如果不能立即取出,则可以等待timeout参数的时间,如果超过这个时间还不能取出任务,则返回null;
  2. take():从blocking阻塞队列取出一个任务,如果BlockingQueue为空,阻断进入等待状态直到BlockingQueue有新的任务被加入为止。

到这里,我们就很好地解释了,当allowCoreThreadTimeOut=true或者此时工作线程大于corePoolSize时,线程调用BlockingQueue的poll方法获取任务,若超过keepAliveTime时间,则返回null,timedOut=true,则getTask会返回null,线程中的runWorker方法会退出while循环,线程接下来会被回收。

下面我们测试一下:

以上所述是小编给大家介绍的java线程池设置详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

相关文章

  • SpringBoot从yml配置文件中读常用参数值实例方法

    SpringBoot从yml配置文件中读常用参数值实例方法

    在本篇文章里小编给大家整理了关于SpringBoot从yml配置文件中读常用参数值实例方法,有需要的朋友们学习下。
    2019-12-12
  • Java容器源码LinkedList原理解析

    Java容器源码LinkedList原理解析

    这篇文章主要介绍了Java容器源码LinkedList原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • Java之Spring注解配置bean实例代码解析

    Java之Spring注解配置bean实例代码解析

    这篇文章主要介绍了Java之Spring注解配置bean实例代码解析,具有一定参考价值,文中还有有关Spring学习的资料下载链接及相关内容推荐,需要的朋友可以了解下。
    2017-09-09
  • Java SpringAOP技术之注解方式详解

    Java SpringAOP技术之注解方式详解

    这篇文章主要为大家详细介绍了Java SpringAOP技术之注解方式,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • Java实现双端链表LinkedList

    Java实现双端链表LinkedList

    本文主要介绍了Java实现双端链表LinkedList,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • SpringCloud Alibaba使用Seata处理分布式事务的技巧

    SpringCloud Alibaba使用Seata处理分布式事务的技巧

    在传统的单体项目中,我们使用@Transactional注解就能实现基本的ACID事务了,随着微服务架构的引入,需要对数据库进行分库分表,每个服务拥有自己的数据库,这样传统的事务就不起作用了,那么我们如何保证多个服务中数据的一致性呢?跟随小编一起通过本文了解下吧
    2021-06-06
  • SpringBoot集成slf4j2日志配置的实现示例

    SpringBoot集成slf4j2日志配置的实现示例

    本文主要介绍了SpringBoot集成slf4j2日志配置的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-08-08
  • Maven中利用assembly插件打包jar包

    Maven中利用assembly插件打包jar包

    本文详细讲解了Maven中利用assembly插件打包jar包的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-12-12
  • spring framework源码调试技巧

    spring framework源码调试技巧

    这篇文章给大家介绍了spring-framework源码调试方法,可以直接将最新代码clone到本地,如果想在代码做一些注释,也可以Fork到自己的仓库。本文采用Fork的方式,并添加了测试module,感兴趣的朋友一起看看吧
    2021-10-10
  • Java实现时间动态显示方法汇总

    Java实现时间动态显示方法汇总

    这篇文章主要介绍了Java实现时间动态显示方法汇总,很实用的功能,需要的朋友可以参考下
    2014-08-08

最新评论