在不停服务的基础上动态修改线程池的最大线程数

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

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 扩展

动态修改空闲线程存活时间等线程池参数的实现方式也可以采用类似方式实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ability Liao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值