在高并发的系统中,合理配置线程池是提高系统稳定性与效率的关键。然而,在不断变化的业务场景下,静态的线程池配置往往难以适应所有情形。借助Spring Boot强大的自动化配置以及Apollo配置中心的动态配置能力,我们可以实现线程池参数的动态调整。
小义这里使用的是spring提供的ThreadPoolTaskExecutor,核心代码如下:
public class ThreadPoolTaskExecutor extends ExecutorConfigurationSupport
implements AsyncListenableTaskExecutor, SchedulingTaskExecutor {
// 核心参数包括:
private int corePoolSize; // 核心线程数
private int maxPoolSize; // 最大线程数
private int keepAliveSeconds; // 线程空闲后的存活时间
private int queueCapacity; // 队列容量
...
}
至于springboot整合apollo,这里就不多介绍了,网上都是教程。不过还是得建议大家从官方文档入手,地址:https://www.apolloconfig.com/#/zh/client/java-sdk-user-guide。
下面创建线程池配置类和属性类。
@ConfigurationProperties(prefix = "threadpool")
public class ThreadPoolProperties {
// 属性声明
}
@Configuration
@EnableConfigurationProperties(ThreadPoolProperties.class)
public class ThreadPoolConfig {
// 创建线程池的Bean
}
通过apollo配置动态监听配置变化。
@Component
public class ThreadPoolConfigChangeListener {
private final ThreadPoolTaskExecutor executor;
private final ThreadPoolProperties properties;
public ThreadPoolConfigChangeListener(ThreadPoolTaskExecutor executor,
ThreadPoolProperties properties) {
this.executor = executor;
this.properties = properties;
}
@ApolloConfigChangeListener
public void onChange(ConfigChangeEvent changeEvent) {
boolean corePoolSizeChanged = changeEvent.isChanged("threadpool.coreSize");
boolean maxPoolSizeChanged = changeEvent.isChanged("threadpool.maxSize");
boolean queueCapacityChanged = changeEvent.isChanged("threadpool.queueCapacity");
if (corePoolSizeChanged || maxPoolSizeChanged || queueCapacityChanged) {
// 核心线程数(corePoolSize)可以热更新
if (corePoolSizeChanged) {
int newCorePoolSize = properties.getCoreSize();
executor.setCorePoolSize(newCorePoolSize);
}
// 最大线程数(maxPoolSize)可以热更新
if (maxPoolSizeChanged) {
int newMaxPoolSize = properties.getMaxSize();
executor.setMaxPoolSize(newMaxPoolSize);
}
// 队列容量(queueCapacity)更新复杂,不能直接修改现有的队列实例
if (queueCapacityChanged) {
// 可以通过新建队列及线程池实例来实现队列容量的更新
}
// 执行修复旧任务持有的线程
executor.afterPropertiesSet();
}
}
}
这样就可以简单的实现动态线程池配置了,需要注意的是,调整线程池参数必须需要谨慎地评估和测试,以防止系统在动态调整后出现资源不足或过度资源闲置的问题。
下面介绍下参数变动后线程池的行为变化:
当然,apollo只是用来存放线程池参数,也可以选择其他的配置中心,最后附一张常见配置中心对比图。