1 概述
在不停服务的基础上改变线程池的最大线程数,并使改变生效,关键点如下:
(1)通过线程池自带的方法设置线程池的最大线程数。
(2)通过配置中心触发线程池的最大线程数的改变。
2 具体实现
自定义线程池,并借助于apollo配置中心,对Apollo配置进行动态监听。
@Slf4j
public class ThreadPoolUtils {
private static final int CORE_SIZE = Runtime.getRuntime().availableProcessors() * 2;
private static final int MAX_SIZE = CORE_SIZE + 10;
private static final int WORK_QUEUE_CAPACITY = 10000;
private static final long KEEP_ALIVE_TIME = 120;
private static final TimeUnit SECOND = TimeUnit.SECONDS;
private static final ThreadPoolExecutor executor;
// 最大线程数apollo配置key
private static final String threadPoolUtils_maxPoolSize_apollo_key = "threadPoolUtils.maxPoolSize";
private static ConfigChange change;
static {
executor = new ThreadPoolExecutor(CORE_SIZE, MAX_SIZE, KEEP_ALIVE_TIME, SECOND, new LinkedBlockingDeque<>(WORK_QUEUE_CAPACITY));
// 监听apollo配置,动态修改线程池参数
updateThreadPoolPram();
}
// 核心线程数apollo配置key
private static final String executorUtilsCorePoolSize = "executorUtils.corePoolSize";
// 最大线程数apollo配置key
private static final String executorUtilsMaxPoolSize = "executorUtils.maxPoolSize";
/**
* 监听apollo配置,动态修改线程池参数
*/
public static void updateThreadPoolPram() {
ConfigService.getConfig("application.yml").addChangeListener(changeEvent -> {
// 核心线程数
updateCorePoolSize(changeEvent);
// 最大线程数
updateMaxPoolSize(changeEvent);
});
}
private static void updateCorePoolSize(ConfigChangeEvent changeEvent) {
if (changeEvent.isChanged(executorUtilsCorePoolSize)) {
ConfigChange change = changeEvent.getChange(executorUtilsCorePoolSize);
String oldValue = change.getOldValue();
String newValue = change.getNewValue();
if (!Objects.equals(oldValue, newValue)) {
try {
int newCorePoolSize = Integer.parseInt(newValue);
// 校验核心线程数有效性
if (newCorePoolSize < 0) {
log.warn("ThreadPoolUtils updateCorePoolSize 核心线程数不能小于0, 忽略此次修改, 新值:{}", newCorePoolSize);
return;
}
// 校验核心线程数不能超过最大线程数
if (newCorePoolSize > executor.getMaximumPoolSize()) {
log.warn("ThreadPoolUtils updateCorePoolSize 核心线程数不能大于最大线程数, 忽略此次修改, 新值:{}, 最大线程数:{}",
newCorePoolSize, executor.getMaximumPoolSize());
return;
}
int corePoolSizeOld = executor.getCorePoolSize();
executor.setCorePoolSize(newCorePoolSize);
log.info("ThreadPoolUtils updateCorePoolSize 核心线程数修改成功, 旧值:{}, 新值:{}", corePoolSizeOld, executor.getCorePoolSize());
} catch (Exception e) {
log.error("ThreadPoolUtils updateCorePoolSize 修改核心线程数异常, 忽略此次修改, 新值:{}", newValue);
}
}
}
}
private static void updateMaxPoolSize(ConfigChangeEvent changeEvent) {
if (changeEvent.isChanged(executorUtilsMaxPoolSize)) {
ConfigChange change = changeEvent.getChange(executorUtilsMaxPoolSize);
String oldValue = change.getOldValue();
String newValue = change.getNewValue();
if (!Objects.equals(oldValue, newValue)) {
try {
int newMaxPoolSize = Integer.parseInt(newValue);
// 校验最大线程数有效性
if (newMaxPoolSize < 0) {
log.warn("ThreadPoolUtils updateMaxPoolSize 最大线程数不能小于0, 忽略此次修改, 新值:{}", newMaxPoolSize);
return;
}
// 校验最大线程数不能小于核心线程数
if (newMaxPoolSize < executor.getCorePoolSize()) {
log.warn("ThreadPoolUtils updateMaxPoolSize 最大线程数新值小于核心线程数, 忽略此次修改, 新值:{}, 核心线程数:{}",
newMaxPoolSize, executor.getCorePoolSize());
return;
}
int maximumPoolSizeOld = executor.getMaximumPoolSize();
executor.setMaximumPoolSize(newMaxPoolSize);
log.info("ThreadPoolUtils updateMaxPoolSize 最大线程数修改成功, 旧值:{}, 新值:{}", maximumPoolSizeOld, executor.getMaximumPoolSize());
} catch (Exception e) {
log.error("ThreadPoolUtils updateMaxPoolSize 修改最大线程数异常, 忽略此次修改, 新值:{}", newValue);
}
}
}
}
/**
* 提交任务到线程池
*/
public static void submitTask(String taskDesc, Runnable task) {
log.info("异步任务[{}]提交线程池....", taskDesc);
try {
executor.execute(task);
} catch (Exception e) {
log.error("异步任务[{}]提交线程池失败,error:", taskDesc, e);
}
}
public static ThreadPoolExecutor getThreadPoolExecutor() {
return executor;
}
}
3 扩展
动态修改空闲线程存活时间等线程池参数的实现方式也可以采用类似方式实现。

本文介绍了如何在Java中自定义线程池,并利用Apollo配置中心实现实时动态调整线程池的最大线程数,同时提及了扩展至核心线程数和空闲线程存活时间的可能方法。
172万+

被折叠的 条评论
为什么被折叠?



