ThreadPoolTaskExecutor 中 corePoolSize vs. maxPoolSize
1. 概览
Spring中的 ThreadPoolTaskExecutor 是一个 JavaBean ,提供围绕java.util.concurrent.ThreadPoolExecutor 的抽象实例,并作为Spring 中org.springframework.core.task.TaskExecutor 暴露出来. 此外,它可以通过corePoolSize、maxPoolSize、queueCapacity、allowCoreThreadTimeOut和keepAliveSeconds的属性进行高度配置。在本教程中,我们将查看corePoolSize和maxPoolSize属性。
2. corePoolSize vs. maxPoolSize
刚接触到这种抽象的用户可能很容易混淆这两个配置属性的区别。因此,让我们分别看一下。
2.1. corePoolSize
corePoolSize 是在不超时情况下,保持活跃的最少线程数 。它是ThreadPoolTaskExecutor的一个可配置项。但是, ThreadPoolTaskExecutor* 抽象将该值的设置委托给底层的java.util.concurrent.ThreadPoolExecutor。为验证这一点,如果我们将allowCoreThreadTimeOut设置为true,那么所有线程都可能超时,等于将corePoolSize的值设置为零。
2.2. maxPoolSize
相反,maxPoolSize定义了可以创建的最大线程数。类似地,ThreadPoolTaskExecutor的maxPoolSize属性也将其值委托给底层的java.util.concurrent.ThreadPoolExecutor。为验证这点, maxPoolSize依赖于queueCapacity,因为ThreadPoolTaskExecutor只会在其队列中的项目数超过queueCapacity*时创建一个新线程。
3. 所以,区别在哪?
corePoolSize和maxPoolSize之间的差别似乎很明显。然而,他们的行为有些微妙之处。
当我们向ThreadPoolTaskExecutor提交新任务时,如果正在运行的线程少于corePoolSize线程,即使池中有空闲线程,或者如果正在运行的线程少于maxPoolSize且由queueCapacity定义的队列已满,它也会创建一个新线程。
接下来,让我们看一些代码,以了解每个属性何时启动的示例。
4. 举例说明
首先,假设我们有一个执行新线程的方法,它来自名为startThreads的ThreadPoolTaskExecutor:
public void startThreads(ThreadPoolTaskExecutor taskExecutor, CountDownLatch countDownLatch,
int numThreads) {
for (int i = 0; i < numThreads; i++) {
taskExecutor.execute(() -> {
try {
Thread.sleep(100L * ThreadLocalRandom.current().nextLong(1, 10));
countDownLatch.countDown();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
}
让我们测试ThreadPoolTaskExecutor的默认配置,它定义了一个线程的corePoolSize、一个无限制的maxPoolSize和无限制的queueCapacity。因此,我们希望无论启动多少任务,都只运行一个线程:
@Test
public void whenUsingDefaults_thenSingleThread() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.afterPropertiesSet();
CountDownLatch countDownLatch = new CountDownLatch(10);
this.startThreads(taskExecutor, countDownLatch, 10);
while (countDownLatch.getCount() > 0) {
Assert.assertEquals(1, taskExecutor.getPoolSize());
}
}
现在,让我们将corePoolSize更改为最多5个线程,并确保它的行为与建议中的一样。因此,无论提交给ThreadPoolTaskExecutor的任务数是多少,我们都希望启动五个线程:
@Test
public void whenCorePoolSizeFive_thenFiveThreads() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(5);
taskExecutor.afterPropertiesSet();
CountDownLatch countDownLatch = new CountDownLatch(10);
this.startThreads(taskExecutor, countDownLatch, 10);
while (countDownLatch.getCount() > 0) {
Assert.assertEquals(5, taskExecutor.getPoolSize());
}
}
类似地,我们可以将maxPoolSize增加到10,而将corePoolSize保留为5。因此,我们希望只启动五个线程。为了更加清晰表明只有五个线程启动,因此queueCapacity仍然是无限制的:
@Test
public void whenCorePoolSizeFiveAndMaxPoolSizeTen_thenFiveThreads() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(5);
taskExecutor.setMaxPoolSize(10);
taskExecutor.afterPropertiesSet();
CountDownLatch countDownLatch = new CountDownLatch(10);
this.startThreads(taskExecutor, countDownLatch, 10);
while (countDownLatch.getCount() > 0) {
Assert.assertEquals(5, taskExecutor.getPoolSize());
}
}
此外,我们现在将重复前面的测试,但将queueCapacity增加到10,并启动20个线程。因此,我们现在希望总共启动十个线程:
@Test
public void whenCorePoolSizeFiveAndMaxPoolSizeTenAndQueueCapacityTen_thenTenThreads() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(5);
taskExecutor.setMaxPoolSize(10);
taskExecutor.setQueueCapacity(10);
taskExecutor.afterPropertiesSet();
CountDownLatch countDownLatch = new CountDownLatch(20);
this.startThreads(taskExecutor, countDownLatch, 20);
while (countDownLatch.getCount() > 0) {
Assert.assertEquals(10, taskExecutor.getPoolSize());
}
}
同样,如果我们将queueCapactity设置为零并且只启动了10个任务,那么我们的ThreadPoolTaskExecutor中也会有10个线程。
5. 写在最后
ThreadPoolTaskExecutor是围绕java.util.concurrent.ThreadPoolExecutor的强大抽象,提供了配置corePoolSize、maxPoolSize和queueCapacity的选项。在本教程中,我们查看了corePoolSize和maxPoolSize属性,以及maxPoolSize如何与queueCapacity协同工作,从而使我们能够轻松地为任何用例创建线程池。
代码可在 Github 中找到!
叮叮叮!关注公众号: 锅外的大佬 ,加入锅外圈,不定时福利输出,hi欢迎你的加入哦
博客地址: http://www.developlee.top
ThreadPoolTaskExecutor 中 corePoolSize vs. maxPoolSize的更多相关文章
- corePoolSize和maxPoolSize的区别
受限于硬件.内存和性能,我们不可能无限制的创建任意数量的线程,每一台机器允许的最大线程是一个有界值.因此ThreadPoolExecutor管理的线程数量是有界的.线程池就是用这些有限个数的线程,去执 ...
- Spring中的线程池和定时任务功能
1.功能介绍 Spring框架提供了线程池和定时任务执行的抽象接口:TaskExecutor和TaskScheduler来支持异步执行任务和定时执行任务功能.同时使用框架自己定义的抽象接口来屏蔽掉底层 ...
- JAVA线程池学习,ThreadPoolTaskExecutor和ThreadPoolExecutor有何区别?
初学者很容易看错,如果没有看到spring或者JUC源码的人肯定是不太了解的. ThreadPoolTaskExecutor是spring core包中的,而ThreadPoolExecutor是JD ...
- java 线程池(ExecutorService与Spring配置threadPoolTaskExecutor)
一.java ExecutorService实现 创建ExecutorService变量private ExecutorService executor = null 2.执行对应任务时,首先生成线程 ...
- spring线程池ThreadPoolTaskExecutor与阻塞队列BlockingQueue
一: ThreadPoolTaskExecutor是一个spring的线程池技术,查看代码可以看到这样一个字段: private ThreadPoolExecutor threadPoolExecut ...
- Java中使用ThreadPoolExecutor并行执行独立的单线程任务
Java SE 5.0中引入了任务执行框架,这是简化多线程程序设计开发的一大进步.使用这个框架可以方便地管理任务:管理任务的生命周期以及执行策略. 在这篇文章中,我们通过一个简单的例子来展现这个框架所 ...
- Java网络编程与NIO详解11:Tomcat中的Connector源码分析(NIO)
本文转载 https://www.javadoop.com 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.c ...
- 深入理解NIO(二)—— Tomcat中对NIO的应用
深入理解NIO(二)—— Tomcat中对NIO的应用 老哥行行好,转载和我说一声好吗,我不介意转载的,但是请把原文链接贴大点好吗 Tomcat大致架构 先贴两张图大致看一眼Tomcat的架构 Tom ...
- Java线程池实现原理及其在美团业务中的实践
本文转载自Java线程池实现原理及其在美团业务中的实践 导语 随着计算机行业的飞速发展,摩尔定律逐渐失效,多核CPU成为主流.使用多线程并行计算逐渐成为开发人员提升服务器性能的基本武器.J.U.C提供 ...
随机推荐
- MHRD_Guide
@(Steam蒸汽动力)[MHRD|Game|How To] [CH]游戏解决方案 1.解决方案将作为完整的代码呈现,部分结决方案将有理论分析或图解. 2.根据记录板判断,解决方案远非理想. 3.慎重 ...
- Visual studio2019配置OPENCV 时属性管理器中没有Microsoft.Cpp.x64.user的解决办法
方法一:重新下载Visual studio2017,再次打开2019就会出现Microsoft.Cpp.x64.user,感觉有些麻烦,也占电脑空间,推荐方法二. 方法二:与方法一原理相同,下载201 ...
- 关于js传送json到.net后台处理
这里的内容好像跟标题不太符合,应该是如何实现将请求得到的结果作为另一个请求的请求参数,方法就是使用json处理配合全局变量进行处理 今天做项目遇到以下情景,页面请求获得一个list数据,然后要将得到的 ...
- Python安装3 —— Python3.8和2.7共存
本文内容皆为作者原创,如需转载,请注明出处:https://www.cnblogs.com/xuexianqi/p/12400896.html 一:Python解释器为什么要2个版本? 众所周知,Py ...
- 某图片站反爬加密字段x-api-key破解
前言 此次逆向的是某“你们都懂”领域的图片站,目前此站限制注册,非会员无法访问:前两天偶然搞到了份邀请码,进入后发现质量还可以,于是尝试爬取,在爬虫编写过程中发现此站点采用了不少手段来阻止自动化脚本( ...
- CSS单位计算总结
CSS单位总结 公共部分css body { background-color: #000; color: skyblue; margin: 0; padding: 0; } body>div& ...
- JavaScript常见的六种继承方式
前言 面向对象编程很重要的一个方面,就是对象的继承.A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法.这对于代码的复用是非常有用的. 大部分面向对象的编程语言,都是通过"类 ...
- vue实现选中效果
前情提要 好久没有写Vue了,略有生疏,这个东西还是得多用.下午看到一个需求,选择相册图片作为轮播图显示.接口返回相册列表,用户选一下再扔回去.直到我看到e.target.className我就知道这 ...
- js事件的三个阶段
js事件的三个阶段分别为:捕获.目标.冒泡 1.捕获:事件由页面元素接收,逐级向下,到具体的元素 2.目标:具体的元素本身 3.冒泡:跟捕获相反,具体元素本身,逐级向上,到页面元素 IE5.5:div ...
- axios下载文件乱码问题 无法解压 文件损坏
/* 下载附件 */ downloadFile(fileName) { // window.open(url); var that = this; var url = "PO2116&quo ...