环境:JDK17 + Nacos2.1.0
1. 简介
本文旨在探讨如何结合Nacos作为动态配置中心,实现在线动态修改线程池大小的功能。将线程池大小的配置信息动态地传递给应用程序。此外,我们还将讨论如何在应用程序中监听配置变化,并根据新的配置信息动态地调整线程池的大小。通过这种方式,我们可以提高系统的灵活性和可扩展性,更好地适应业务需求的变化。
2. 实战案例
我们不会在SpringBoot项目中去使用,只是通过普通的maven项目进行演示。
2.1 依赖管理
2.1.2
1.33
17
com.alibaba.nacos
nacos-client
${nacos.version}
pure
com.alibaba.nacos
nacos-common
${nacos.version}
com.alibaba.nacos
nacos-api
${nacos.version}
org.yaml
snakeyaml
${yaml.version}
2.2 Nacos中初始配置
在Nacos中进行线程池(核心数,最大数)初始配置
图片
2.3 自定义Nacos监听器
编写Nacos配置发生变化的监听器,该监听器的作用就是用来修改线程池的核心线程池数及最大线程数。
public class NacosConfigListener {
public void start() throws Exception {
String serverAddr = "localhost:8848";
String dataId = "dy-thread.yaml";
String group = "dy";
Properties properties = new Properties();
properties.put("serverAddr", serverAddr);
properties.put("username", "nacos") ;
properties.put("password", "nacos") ;
ConfigService configService = NacosFactory.createConfigService(properties);
String content = configService.getConfig(dataId, group, 5000);
System.out.println("初始配置:n" + content) ;
Yaml yaml = new Yaml() ;
configService.addListener(dataId, group, new Listener() {
public void receiveConfigInfo(String configInfo) {
try {
LinkedHashMap content = (LinkedHashMap) yaml.load(configInfo) ;
System.out.println("监听线程池修改:" + content) ;
// 当内容发生变化后,修改线程池的配置信息
LinkedHashMap dy = (LinkedHashMap) content.get("dy") ;
Integer coreSize = (Integer) dy.get("coreSize") ;
Integer maximumPoolSize = (Integer) dy.get("maximumPoolSize") ;
DynamicThreadPoolConfig.pool.setMaximumPoolSize(maximumPoolSize) ;
DynamicThreadPoolConfig.pool.setCorePoolSize(coreSize) ;
} catch (Exception e) {
e.printStackTrace() ;
}
}
@Override
public Executor getExecutor() {
return null ;
}
});
}
}
2.4 线程池使用
这里简单模拟使用线程池执行任务。
public class DynamicThreadPoolConfig {
public static final ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 3, 60, TimeUnit.SECONDS, new ArrayBlockingQueue(100)) ;
public static void main(String[] args) throws Exception {
// 启动监听器
new NacosConfigListener().start() ;
var schedule = new ScheduledThreadPoolExecutor(1) ;
// 以固定的周期打印线程池线程信息
schedule.scheduleAtFixedRate(() -> {
System.out.println(
"核心线程数: " + pool.getCorePoolSize()
+ ", 最大线程数: " + pool.getMaximumPoolSize()
+ ", 当前活动任务数: " + pool.getActiveCount()
) ;
}, 0, 3, TimeUnit.SECONDS) ;
// 动态添加任务
for (var i = 0; i {
try {
System.out.println(Thread.currentThread().getName()) ;
TimeUnit.SECONDS.sleep(10) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
}) ;
}
}
}
2.5 测试
直接运行程序,控制台如下输出
图片
输出的都是默认值。接下来,通过nacos界面修改线程池大小
图片
控制台输出
图片
程序正确的监听到了配置发生了变化,同时修改了线程池的大小。
总结:
在实际生产环境下,动态修改线程池大小具有重要意义。以下是一些主要的原因:
总之,动态修改线程池大小可以帮助应用程序更好地适应负载变化、应对突发流量,并提高系统的灵活性和可扩展性。这对于保持应用程序的稳定性和性能,以及满足不断变化的业务需求具有重要意义。