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提供 ...
随机推荐
- 【内推】平安产险大数据测试开发工程师,15-30k!
平安产险技术岗内部推荐-大数据测试开发工程师等-欢迎中年人和2020应届生 上班地点:深圳福田平安金融中心 另有大量 上海 北京 成都 广州 岗位 交流qq群 828186629 微信pythonte ...
- 烧钱时代终结!O2O还能玩啥花样?
最终的最终,饱受亏损.烧钱玩补贴等争议的美团还是追随滴滴/快的.赶集/58的步伐,与大众点评愉快的在一起了!美团和大众点评作为O2O行业的领军企业,都因为不堪忍受持续地投入却不见回报的模式而不得不放低 ...
- 基于layPage分页插件浅析两种分页方式
最近在开发过程中经常用到分页,今天挤出些时间来捋一捋自己的经验 在web开发中,一般显示数据列表页时,我们会用到分页控件来显示数据.采用分页一般基于两种不同的需求,一种是数据量不算很大,但是在页面展示 ...
- python列表解析补充:
python列表解析补充: # 补充: f = [x + y for x in 'ABCDE' for y in '1234567'] print(f) test = [] for x in 'ABC ...
- Samtec与Neoconix达成合作并和II-VI推出新产品
序言:Samtec近日动作不断, 近日Samtec与Neoconix达成合作并和II-VI推出新产品,以下是详细内容. Samtec与Neoconix签订Neoconix PCBeam 技术授权协议, ...
- Kali系统中20个超好用黑客渗透工具,你知道几个?
1. Aircrack-ng Aircrack-ng是用来破解WEP/WAP/WPA 2无线密码最佳的黑客工具之一! 它通过接收网络的数据包来工作,并通过恢复的密码进行分析.它还拥有一个控制台接口.除 ...
- 对象深拷贝deepCopy
function type(obj){ return Object.prototype.toString.call(obj).slice(8,-1); } function deepCopy(targ ...
- Java基础--选择排序
每一趟从待排序的数据元素中选出最小(或最大的)一个元素, 顺序放在已排好的序的数列的最后,直到全部待排序的数据元素排完. 选择排序是不稳定的排序方法. 选择排序的时间复杂度为 O(n^2). 第一次需 ...
- 基于springcloud框架搭建项目-Eureka篇(一)
springcloud项目近年来算是很流行的了,不少公司项目目前都用到了,毕竟优点很多,刚好公司项目用到了,根据自己的理解,简单搭建一下,以便以后学习 这里简单的介绍一下它: SpringCloud, ...
- 从0系统学Android--5.2 发送广播
从0系统学Android--52 发送广播 本系列文章目录:更多精品文章分类 本系列持续更新中.... 初级阶段内容参考<第一行代码> 5.3 发送自定义广播 前面已经学习了如何接受广播了 ...