深入 Java 线程池:核心线程数动态调整技术详解与实战

线程池参数如何设定?如何动态调整线程池?生产级动态治理全方案 上述在实际生产环境中,根据经验值设定线程池参数的静态配置往往无法满足业务的动态变化需求,因此需要采用。:在 Spring Boot 微服务架构下,通过配置中心动态修改线程池参数。等问题,从而优化线程池的参数配置。策略,以提高系统的吞吐量和稳定性。:复杂业务,基于历史数据预测流量高峰,提前调整线程池大小。在实际生产环境中,监控线程池的运行状态可以帮助我们发现。在生产环境中,线程池的参数不宜固定,而应支持。,以适应不同的业务负载。采集和展示线程池监控数据。中创建仪表盘,查看线程池的。:高并发场景下,结合。 阅读详情

大家好,今天我要和大家分享一个 Java 多线程开发中很实用但不太被重视的技巧 - 如何在线程池运行过程中动态调整核心线程数。这个能力在系统负载动态变化的场景下特别有用,能帮我们实现更灵活的资源调配。

一、核心问题:线程池核心线程数能否运行时修改?

先直接回答:能! ThreadPoolExecutor 确实支持在运行时动态修改核心线程数。

Java 中的 ThreadPoolExecutor 类提供了setCorePoolSize(int corePoolSize)方法,允许我们在线程池运行过程中修改核心线程数。这个功能非常实用,但很多开发者并不知道或者不确定如何正确使用它。

二、线程池基础知识回顾

在深入讨论前,我们先快速回顾一下线程池的基本概念:

Java 线程池中几个关键参数:

  • corePoolSize: 核心线程数,线程池会一直保持这些线程活跃
  • maximumPoolSize: 最大线程数,线程池可以创建的最大线程数量
  • workQueue: 工作队列,当所有核心线程都在工作时,新任务会放在这里等待
  • keepAliveTime: 非核心线程的空闲存活时间

线程池状态与核心线程数调整的关系

ThreadPoolExecutor 内部维护着一个状态变量,定义了线程池的几种关键状态:

在不同状态下调整核心线程数的行为:

  • RUNNING:正常运行状态,可以完全接受setCorePoolSize的调整
  • SHUTDOWN:不再接受新任务,但会处理队列中的任务。此时仍可以调用setCorePoolSize,但不会创建新的线程
  • STOP:不接受新任务,也不处理队列任务,中断正在执行的任务。此时调用setCorePoolSize无实际效果
  • TIDYING/TERMINATED:调用setCorePoolSize无效

队列类型对线程池行为的影响

线程池使用的队列类型对其行为有重大影响:

  • 无界队列(如LinkedBlockingQueue无参构造):队列理论上无容量限制,会导致maximumPoolSize参数实际上被忽略,因为队列永远不会满,线程池不会创建超过核心线程数的线程。此时,动态调整核心线程数是控制并发的唯一手段。
  • 有界队列(如ArrayBlockingQueue或指定容量的LinkedBlockingQueue):当队列满时,线程池会创建新线程直到达到最大线程数,此时核心线程数和最大线程数都能影响线程池行为。
// 无界队列示例 - maximumPoolSize实际不起作用
ThreadPoolExecutor unboundedPoolExecutor = new ThreadPoolExecutor(
        5, 10, 60, TimeUnit.SECONDS,
        new LinkedBlockingQueue<>());  // 无界队列

// 有界队列示例 - 可以用到maximumPoolSize
ThreadPoolExecutor boundedPoolExecutor = new ThreadPoolExecutor(
        5, 10, 60, TimeUnit.SECONDS,
        new LinkedBlockingQueue<>(100));  // 有界队列,容量100

三、动态修改核心线程数的方法

1. 基本用法

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolCoreModifyDemo {
    public static void main(String[] args) {
        // 创建线程池,初始核心线程数为2,最大线程数为5
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2,
                5,
                60, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(10));

        System.out.println("初始核心线程数: " + executor.getCorePoolSize());

        // 修改核心线程数为4
        executor.setCorePoolSize(4);

        System.out.println("修改后核心线程数: " + executor.getCorePoolSize());

        // 关闭线程池
        executor.shutdown();
    }
}

就是这么简单!通过setCorePoolSize()方法,我们能在运行时随时调整线程池的核心线程数。

2. 动态调整实战案例

下面看一个更完整的例子,展示如何根据系统负载动态调整核心线程数:

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class DynamicThreadPoolDemo {
    public static void main(String[] args) throws InterruptedException {
        // 创建线程池,初始核心线程数为2
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2,
                10,
                60, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(100),
                new ThreadFactory() {
                    private final AtomicInteger counter = new AtomicInteger(1);
                    @Override
                    public Thread newThread(Runnable r) {
                        return new Thread(r, "工作线程-" + counter.getAndIncrement());
                    }
                },
                new ThreadPoolExecutor.CallerRunsPolicy());

        // 预热线程池,让核心线程提前创建出来
        executor.prestartAllCoreThreads();
        System.out.println("初始核心线程数: " + executor.getCorePoolSize());
        System.out.println("当前活跃线程数: " + executor.getActiveCount());

        // 模拟低负载阶段 - 提交5个任务
        submitTasks(executor, 5, "低负载任务");
        Thread.sleep(2000);
        System.out.println("低负载阶段 - 活跃线程数: " + executor.getActiveCount());

        // 模拟高负载来临 - 先增加核心线程数
        System.out.println("\n⚠️ 检测到高负载,将核心线程数从2调整到5");
        executor.setCorePoolSize(5);
        System.out.println("调整后核心线程数: " + executor.getCorePoolSize());

        // 预热新增的核心线程
        executor.prestartAllCoreThreads();
        System.out.println("当前活跃线程数: " + executor.getActiveCount());

        // 模拟高负载阶段 - 提交20个任务
        submitTasks(executor, 20, "高负载任务");
        Thread.sleep(2000);
        System.out.println("高负载阶段 - 活跃线程数: " + executor.getActiveCount());

        // 模拟负载下降 - 减少核心线程数
        System.out.println("\n⚠️ 检测到负载下降,将核心线程数从5调整回3");
        executor.setCorePoolSize(3);
        System.out.println("调整后核心线程数: " + executor.getCorePoolSize());

        // 等待任务处理完毕
        Thread.sleep(5000);
        System.out.println("负载下降后 - 活跃线程数: " + executor.getActiveCount());

        // 关闭线程池
        executor.shutdown();
        executor.awaitTermination(10, TimeUnit.SECONDS);
    }

    private static void submitTasks(ThreadPoolExecutor executor, int count, String prefix) {
        System.out.println("提交" + count + "个" + prefix + "任务...");
        for (int i = 1; i <= count; i++) {
            final int taskId = i;
            executor.submit(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + " 执行" + prefix + "-" + taskId);
                    // 模拟任务执行时间
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                return taskId;
            });
        }
    }
}

这个例子模拟了一个真实场景:系统检测到负载变化,动态调整线程池核心线程数以适应不同的工作量。

3. prestartAllCoreThreads 方法的关键作用

在上面的例子中,我们使用了prestartAllCoreThreads()方法,这个方法有什么特别之处?

  • 提前创建线程:该方法会立即创建所有核心线程,而不是等待任务提交时才按需创建
  • 避免冷启动延迟:首次提交任务时不需要等待线程创建,立即处理
  • 动态调整后的预热:当我们增加核心线程数后,调用此方法能立即创建新增的核心线程,即使队列中没有等待的任务
  • 适用场景:系统启动时、负载预期即将上升时、核心线程数调整后
// 示例:增加核心线程数后立即创建线程的效果
ThreadPoolExecutor executor = new ThreadPoolExecutor(
        2, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100));

// 初始预热 - 创建2个核心线程
int prestarted = executor.prestartAllCoreThreads();
System.out.println("预热创建线程数: " + prestarted);  // 输出: 2

// 增加核心线程数
executor.setCorePoolSize(5);

// 再次预热 - 只会创建新增的3个核心线程
prestarted = executor.prestartAllCoreThreads();
System.out.println("第二次预热创建线程数: " + prestarted);  // 输出: 3

四、核心线程数修改的内部机制

当我们调用setCorePoolSize()时,线程池内部会发生什么呢?让我们看看这个过程:

理解这个机制很重要:

  1. 增加核心线程数:线程池会立即检查等待队列,如果有等待的任务,会立即创建新的核心线程来处理;如果没有等待任务,则不会立即创建新线程,而是在新任务到来时再创建。
  2. 减少核心线程数:线程池不会立即终止多余的核心线程,而是将它们标记为"可回收"。重要的是,默认情况下(allowCoreThreadTimeOut(false))核心线程不会因空闲而被回收,即使核心线程数被调低,多余的核心线程会一直存活。只有设置executor.allowCoreThreadTimeOut(true)后,核心线程才会在空闲超过keepAliveTime时被回收。
// 允许核心线程超时回收示例
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10,
        60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100));

// 设置核心线程也可以超时回收
executor.allowCoreThreadTimeOut(true);

// 此时即使是核心线程,空闲60秒后也会被回收
// 降低核心线程数后,多余的线程会在空闲后被清理

setCorePoolSize 的线程安全性

虽然ThreadPoolExecutor类本身是线程安全的,setCorePoolSize方法也是线程安全的,但在系统中并发调整核心线程数仍需要注意:

// 并发调整核心线程数的潜在问题
public class ConcurrentAdjustmentDemo {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                5, 20, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100));

        // 并发调整示例 - 可能导致意外结果
        new Thread(() -> {
            executor.setCorePoolSize(8);  // 线程1调整到8
            System.out.println("线程1调整后: " + executor.getCorePoolSize());
        }).start();

        new Thread(() -> {
            executor.setCorePoolSize(3);  // 线程2调整到3
            System.out.println("线程2调整后: " + executor.getCorePoolSize());
        }).start();

        // 最终结果取决于哪个线程后执行,可能是3也可能是8
    }
}

建议的解决方案:

// 通过同步机制或单线程调度器控制核心线程数调整
public class SafeAdjustmentDemo {
    private static final Object adjustLock = new Object();
    private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(
            5, 20, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100));

    // 方法1:使用同步锁
    public static void adjustCorePoolSizeSafely(int newSize) {
        synchronized (adjustLock) {
            System.out.println("调整核心线程数: " + executor.getCorePoolSize() + " -> " + newSize);
            executor.setCorePoolSize(newSize);
        }
    }

    // 方法2:使用单线程调度器(推荐)
    private static final ScheduledExecutorService adjuster =
            Executors.newSingleThreadScheduledExecutor();

    public static void scheduleAdjustment(int newSize) {
        adjuster.execute(() -> {
            System.out.println("调度调整核心线程数: " + executor.getCorePoolSize() + " -> " + newSize);
            executor.setCorePoolSize(newSize);
        });
    }
}

五、动态调整的实际应用场景与监控指标

不同调整策略的适用场景对比

调整策略

适用场景

核心指标

调整频率

实现复杂度

定时调度(日夜模式)

可预测的周期性负载

时间触发

低(小时级)

低

基于队列长度

任务积压敏感型系统

队列长度、活跃线程数

中(秒级)

中

基于性能指标

高动态负载系统

CPU 利用率、吞吐量、延迟

高(秒级以下)

高

混合策略

复杂业务系统

多指标综合评估

可变

高

场景一:日夜负载差异大的系统

比如一个电商系统,白天用户活跃度高,晚上低:

import java.time.LocalTime;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class DayNightThreadPoolAdjuster {

    private final ThreadPoolExecutor executor;
    private final ScheduledExecutorService scheduler;

    // 白天和夜间的核心线程数配置
    private final int daytimeCoreSize = 10;
    private final int nighttimeCoreSize = 3;

    public DayNightThreadPoolAdjuster() {
        // 创建主线程池
        this.executor = new ThreadPoolExecutor(
                nighttimeCoreSize, // 初始使用夜间配置
                20,
                60, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(500),
                new ThreadFactory() {
                    private final AtomicInteger counter = new AtomicInteger(1);
                    @Override
                    public Thread newThread(Runnable r) {
                        return new Thread(r, "业务线程-" + counter.getAndIncrement());
                    }
                });

        // 创建调度器
        this.scheduler = Executors.newScheduledThreadPool(1);

        // 启动自动调整任务
        startAutoAdjustment();
    }

    private void startAutoAdjustment() {
        // 每小时检查一次时间并调整
        scheduler.scheduleAtFixedRate(() -> {
            LocalTime now = LocalTime.now();
            int hour = now.getHour();

            // 判断是白天还是夜间 (假设8:00-22:00为白天)
            if (hour >= 8 && hour < 22) {
                if (executor.getCorePoolSize() != daytimeCoreSize) {
                    System.out.println("当前时间 " + now + ",切换到白天模式,核心线程数: " + daytimeCoreSize);
                    executor.setCorePoolSize(daytimeCoreSize);
                }
            } else {
                if (executor.getCorePoolSize() != nighttimeCoreSize) {
                    System.out.println("当前时间 " + now + ",切换到夜间模式,核心线程数: " + nighttimeCoreSize);
                    executor.setCorePoolSize(nighttimeCoreSize);
                }
            }
        }, 0, 1, TimeUnit.HOURS);
    }

    public ThreadPoolExecutor getExecutor() {
        return executor;
    }

    public void shutdown() {
        scheduler.shutdown();
        executor.shutdown();
    }

    // 示例使用
    public static void main(String[] args) throws InterruptedException {
        DayNightThreadPoolAdjuster adjuster = new DayNightThreadPoolAdjuster();
        ThreadPoolExecutor pool = adjuster.getExecutor();

        // 模拟提交任务
        for (int i = 0; i < 5; i++) {
            pool.submit(() -> {
                System.out.println(Thread.currentThread().getName() + " 执行任务");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }

        // 等待一段时间
        Thread.sleep(5000);

        // 关闭
        adjuster.shutdown();
    }
}

场景二:基于全面监控指标的自适应调整

实际生产环境中,我们应该结合更丰富的监控指标来动态调整线程池参数:

import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class EnhancedAdaptiveThreadPool {

    private final ThreadPoolExecutor executor;
    private final ScheduledExecutorService monitor;

    // 线程池配置参数
    private final int minCoreSize = 2;
    private final int maxCoreSize;
    private final int queueSizeThreshold = 20; // 队列长度阈值

    // 任务性能跟踪
    private final ConcurrentHashMap<Long, Long> taskStartTimes = new ConcurrentHashMap<>();
    private final AtomicInteger totalTasks = new AtomicInteger(0);
    private final AtomicInteger completedTasks = new AtomicInteger(0);
    private double avgProcessingTime = 0;

    public EnhancedAdaptiveThreadPool() {
        // 根据CPU核心数确定最大核心线程数
        int cpuCores = Runtime.getRuntime().availableProcessors();
        this.maxCoreSize = cpuCores * 2; // 一般建议线程数为CPU核心数的1-2倍

        System.out.println("系统CPU核心数:" + cpuCores + ", 设置最大核心线程数:" + maxCoreSize);

        // 创建主线程池
        this.executor = new ThreadPoolExecutor(
                minCoreSize,
                maxCoreSize * 2, // 最大线程数设为核心线程数的2倍
                60, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(100),
                new CustomThreadFactory("自适应线程"),
                new ThreadPoolExecutor.CallerRunsPolicy());

        // 创建监控线程
        this.monitor = Executors.newScheduledThreadPool(1);

        // 启动自动调整
        startMonitoring();
    }

    private static class CustomThreadFactory implements ThreadFactory {
        private final AtomicInteger counter = new AtomicInteger(1);
        private final String prefix;

        public CustomThreadFactory(String prefix) {
            this.prefix = prefix;
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r, prefix + "-" + counter.getAndIncrement());
            // 设置为非守护线程
            thread.setDaemon(false);
            // 设置为正常优先级
            thread.setPriority(Thread.NORM_PRIORITY);
            return thread;
        }
    }

    public <T> Future<T> submit(Callable<T> task) {
        // 包装任务以跟踪性能
        return executor.submit(new Callable<T>() {
            @Override
            public T call() throws Exception {
                long startTime = System.currentTimeMillis();
                long threadId = Thread.currentThread().getId();
                taskStartTimes.put(threadId, startTime);
                totalTasks.incrementAndGet();

                try {
                    return task.call();
                } finally {
                    long endTime = System.currentTimeMillis();
                    taskStartTimes.remove(threadId);
                    completedTasks.incrementAndGet();

                    // 更新平均处理时间(简单滑动平均)
                    double processingTime = endTime - startTime;
                    avgProcessingTime = (avgProcessingTime * 0.8) + (processingTime * 0.2);
                }
            }
        });
    }

    private void startMonitoring() {
        // 每5秒检查一次负载并调整
        monitor.scheduleAtFixedRate(() -> {
            // 获取线程池指标
            int queueSize = executor.getQueue().size();
            int currentCoreSize = executor.getCorePoolSize();
            int activeThreads = executor.getActiveCount();
            int poolSize = executor.getPoolSize();

            // 获取系统CPU使用率
            double cpuLoad = getSystemCpuLoad();

            // 任务吞吐量计算
            int completed = completedTasks.get();
            double throughput = completed / 5.0; // 每秒完成任务数

            // 重置计数器
            completedTasks.set(0);

            System.out.println("== 监控报告 ==");
            System.out.println("CPU使用率: " + String.format("%.2f", cpuLoad * 100) + "%");
            System.out.println("队列长度: " + queueSize);
            System.out.println("当前核心线程数: " + currentCoreSize);
            System.out.println("当前线程池大小: " + poolSize);
            System.out.println("活跃线程数: " + activeThreads);
            System.out.println("任务吞吐量: " + String.format("%.2f", throughput) + "任务/秒");
            System.out.println("平均处理时间: " + String.format("%.2f", avgProcessingTime) + "ms");

            // 计算理想线程数
            // Little's Law: 并发数 = 吞吐量 × 响应时间
            int idealThreadCount = Math.max(minCoreSize, (int) Math.ceil(throughput * (avgProcessingTime / 1000.0)));
            idealThreadCount = Math.min(idealThreadCount, maxCoreSize);

            // 基于多种指标综合决策
            boolean highLoad = queueSize > queueSizeThreshold ||
                              (activeThreads >= currentCoreSize * 0.8) ||
                              (cpuLoad < 0.7 && throughput > currentCoreSize);

            boolean lowLoad = queueSize == 0 &&
                             activeThreads < currentCoreSize * 0.3 &&
                             currentCoreSize > minCoreSize &&
                             cpuLoad < 0.3;

            if (highLoad) {
                // 负载高,需要增加核心线程
                int newCoreSize = Math.min(currentCoreSize + 1, maxCoreSize);
                if (newCoreSize > currentCoreSize) {
                    System.out.println("⚠️ 检测到高负载,增加核心线程数: " + currentCoreSize + " -> " + newCoreSize);
                    executor.setCorePoolSize(newCoreSize);
                }
            } else if (lowLoad) {
                // 负载低,可以减少核心线程
                int newCoreSize = Math.max(currentCoreSize - 1, minCoreSize);
                if (newCoreSize < currentCoreSize) {
                    System.out.println("⚠️ 检测到低负载,减少核心线程数: " + currentCoreSize + " -> " + newCoreSize);
                    executor.setCorePoolSize(newCoreSize);
                }
            } else if (Math.abs(currentCoreSize - idealThreadCount) > 2) {
                // 根据Little's Law调整到理想线程数
                System.out.println("⚠️ 根据性能指标调整,核心线程数: " + currentCoreSize + " -> " + idealThreadCount);
                executor.setCorePoolSize(idealThreadCount);
            }
        }, 5, 5, TimeUnit.SECONDS);
    }

    private double getSystemCpuLoad() {
        OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
        // 这里使用系统平均负载作为参考
        // 在生产环境中,可以使用JMX或其他方法获取更精确的CPU使用率
        double loadAvg = osBean.getSystemLoadAverage();
        if (loadAvg < 0) return 0.5; // 某些系统可能不支持此方法
        return Math.min(loadAvg / Runtime.getRuntime().availableProcessors(), 1.0);
    }

    public ThreadPoolExecutor getExecutor() {
        return executor;
    }

    public void shutdown() {
        monitor.shutdown();
        executor.shutdown();
    }
}

这个增强版的自适应线程池考虑了更多实际生产环境中的指标:

  • CPU 使用率
  • 任务处理的平均时间
  • 任务吞吐量
  • 使用 Little's Law(并发数 = 吞吐量 × 响应时间)计算理想线程数
  • 结合 CPU 核心数动态调整线程池大小

六、修改核心线程数的注意事项

动态调整核心线程数虽然强大,但也需要注意一些问题:

1. 增减核心线程数的不对称性

  • 增加核心线程数:如果等待队列有任务,线程池会立即创建新的核心线程来处理这些任务
  • 减少核心线程数:默认情况下(allowCoreThreadTimeOut=false),核心线程不会因空闲而被回收,即使核心线程数被调低。只有设置allowCoreThreadTimeOut(true)后,多余的核心线程才会在空闲超过 keepAliveTime 后被回收。

2. 对系统资源的影响

调整核心线程数会直接影响系统资源使用:

  • 增加核心线程数会占用更多内存和 CPU 资源
  • 核心线程通常是常驻的,即使没有任务也会保持活跃
  • 在高并发环境下,过多的线程可能导致线程上下文切换增加,反而降低性能

3. 线程池参数的整体调优

动态修改核心线程数应该与其他线程池参数协调配合:

  • keepAliveTime:当设置allowCoreThreadTimeOut(true)时,这个参数决定了空闲核心线程的存活时间。如果频繁调整核心线程数,可以设置较短的 keepAliveTime 避免资源浪费;而在负载稳定的场景,可以设置较长的 keepAliveTime 减少线程创建销毁的开销。
  • 队列容量:过小的队列会导致频繁创建非核心线程,过大的队列可能导致任务积压。对于波动较大的负载,可以设置较小的队列配合动态调整核心线程数。
  • 拒绝策略:在极端负载下,即使动态调整了核心线程数,任务仍可能被拒绝。可以自定义拒绝策略,例如记录日志、放入备用队列或异步重试,避免任务丢失。
// 自定义拒绝策略示例
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    5, 10, 60, TimeUnit.SECONDS,
    new ArrayBlockingQueue<>(100),
    Executors.defaultThreadFactory(),
    new RejectedExecutionHandler() {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            System.err.println("任务被拒绝,当前队列长度:" + e.getQueue().size());
            // 可以将任务放入备用存储(如Redis)或日志系统
            // 也可以在低峰期重新提交
            // Redis示例代码省略
        }
    }
);

七、真实业务场景实战

模拟电商秒杀场景的线程池动态调整

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Random;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class SecKillThreadPoolDemo {

    private static class SecKillTask implements Runnable {
        private final int userId;
        private final int productId;
        private static final Random random = new Random();

        public SecKillTask(int userId, int productId) {
            this.userId = userId;
            this.productId = productId;
        }

        @Override
        public void run() {
            String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss.SSS"));
            try {
                // 模拟处理秒杀请求
                Thread.sleep(200 + random.nextInt(300));
                System.out.println(time + " - " + Thread.currentThread().getName()
                        + " 处理用户" + userId + "的秒杀请求,商品ID: " + productId);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        // 创建秒杀处理线程池,初始核心线程数较小
        ThreadPoolExecutor secKillPool = new ThreadPoolExecutor(
                3,  // 初始核心线程数
                20, // 最大线程数
                60, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(500), // 使用有界队列,避免任务积压导致OOM
                new ThreadFactory() {
                    private final AtomicInteger counter = new AtomicInteger(1);
                    @Override
                    public Thread newThread(Runnable r) {
                        return new Thread(r, "秒杀线程-" + counter.getAndIncrement());
                    }
                },
                new RejectedExecutionHandler() {
                    @Override
                    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                        // 自定义拒绝策略,记录被拒绝的请求并返回秒杀失败
                        if (r instanceof SecKillTask) {
                            SecKillTask task = (SecKillTask) r;
                            System.err.println("⚠️ 系统繁忙,用户" + task.userId + "秒杀请求被拒绝");
                            // 实际场景中可以:
                            // 1. 返回特定的失败信息给用户
                            // 2. 将请求存入备用存储(如Redis)
                            // 3. 记录监控指标,触发容量扩展
                        }
                    }
                });

        // 允许核心线程超时回收,提高资源利用率
        secKillPool.allowCoreThreadTimeOut(true);

        // 模拟秒杀活动监控与调整
        ScheduledExecutorService monitor = Executors.newScheduledThreadPool(1);

        // 用于模拟请求量的计数器
        AtomicInteger requestCounter = new AtomicInteger(0);
        AtomicInteger totalRequestsLastMinute = new AtomicInteger(0);

        // 每10秒评估一次负载并调整线程池
        monitor.scheduleAtFixedRate(() -> {
            int requests = requestCounter.getAndSet(0);
            totalRequestsLastMinute.addAndGet(requests);

            int currentCoreSize = secKillPool.getCorePoolSize();
            int queueSize = secKillPool.getQueue().size();
            int activeThreads = secKillPool.getActiveCount();
            int completedTasks = (int)secKillPool.getCompletedTaskCount();

            System.out.println("\n----- 监控报告 -----");
            System.out.println("过去10秒收到请求: " + requests);
            System.out.println("队列积压任务数: " + queueSize);
            System.out.println("当前核心线程数: " + currentCoreSize);
            System.out.println("当前活跃线程数: " + activeThreads);
            System.out.println("已完成任务数: " + completedTasks);

            // 根据多种指标综合决策调整核心线程数
            // 1. 请求量趋势
            // 2. 队列积压情况
            // 3. 线程利用率(活跃线程/核心线程)
            boolean highLoad = requests > 100 ||
                               queueSize > 50 ||
                               activeThreads >= currentCoreSize * 0.8;

            boolean lowLoad = requests < 20 &&
                              queueSize < 10 &&
                              activeThreads < currentCoreSize * 0.3 &&
                              currentCoreSize > 3;

            if (highLoad) {
                // 高负载情况 - 动态计算理想核心线程数
                // 简单公式:每10个请求/秒对应1个线程(假设每个请求平均处理时间200ms)
                int idealThreads = Math.max(3, requests / 10);
                int newCoreSize = Math.min(Math.min(idealThreads, 15),
                                         secKillPool.getMaximumPoolSize());

                if (newCoreSize > currentCoreSize) {
                    System.out.println("⚠️ 检测到高负载,增加核心线程数: " + currentCoreSize + " -> " + newCoreSize);
                    secKillPool.setCorePoolSize(newCoreSize);

                    // 预热新增的核心线程,提前准备处理请求
                    secKillPool.prestartAllCoreThreads();
                }
            } else if (lowLoad) {
                // 低负载情况 - 缓慢释放资源
                int newCoreSize = Math.max(currentCoreSize - 1, 3);
                if (newCoreSize < currentCoreSize) {
                    System.out.println("⚠️ 检测到低负载,减少核心线程数: " + currentCoreSize + " -> " + newCoreSize);
                    secKillPool.setCorePoolSize(newCoreSize);
                }
            }
        }, 10, 10, TimeUnit.SECONDS);

        // 每5分钟重置计数器
        monitor.scheduleAtFixedRate(() -> {
            int totalRequests = totalRequestsLastMinute.getAndSet(0);
            System.out.println("\n===== 过去5分钟总请求量: " + totalRequests + " =====");
        }, 5, 5, TimeUnit.MINUTES);

        // 模拟秒杀活动波动请求
        ScheduledExecutorService secKillSimulator = Executors.newScheduledThreadPool(1);

        // 模拟正常请求
        secKillSimulator.scheduleAtFixedRate(() -> {
            // 每秒钟产生2-5个请求
            int requestsPerSecond = 2 + new Random().nextInt(4);
            for (int i = 0; i < requestsPerSecond; i++) {
                int userId = 10000 + new Random().nextInt(9000);
                secKillPool.execute(new SecKillTask(userId, 1001));
                requestCounter.incrementAndGet();
            }
        }, 0, 1, TimeUnit.SECONDS);

        // 模拟秒杀活动开始 - 突发大量请求
        Thread.sleep(30000); // 30秒后开始秒杀
        System.out.println("\n\n!!!!! 秒杀活动开始 !!!!!\n\n");

        // 提交大量请求模拟秒杀场景
        for (int i = 0; i < 3; i++) {
            // 模拟3轮高峰
            CompletableFuture.runAsync(() -> {
                try {
                    // 模拟10秒内涌入200个请求
                    for (int j = 0; j < 200; j++) {
                        int userId = 20000 + new Random().nextInt(10000);
                        secKillPool.execute(new SecKillTask(userId, 1001));
                        requestCounter.incrementAndGet();
                        Thread.sleep(50); // 每50ms一个请求
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });

            Thread.sleep(20000); // 每轮高峰间隔20秒
        }

        // 运行一段时间后结束
        Thread.sleep(60000);

        // 关闭所有线程池
        secKillSimulator.shutdown();
        monitor.shutdown();
        secKillPool.shutdown();
        System.out.println("演示结束");
    }
}

这个案例不仅模拟了电商秒杀场景下的线程池动态调整,还强调了:

  1. 使用有界队列避免 OOM
  2. 自定义拒绝策略处理极端情况
  3. 允许核心线程超时回收提高资源利用率
  4. 基于多种指标综合决策调整核心线程数
  5. 在负载高峰前预热线程池

八、进阶:线程工厂选项与线程池监控

更简洁的线程工厂实现

在前面的例子中,我们都是手动实现 ThreadFactory。如果使用 Guava 库,可以更简洁地创建线程工厂:

// 使用Guava的ThreadFactoryBuilder(需引入依赖)
import com.google.common.util.concurrent.ThreadFactoryBuilder;

ThreadFactory factory = new ThreadFactoryBuilder()
    .setNameFormat("业务线程-%d")
    .setDaemon(false)
    .setPriority(Thread.NORM_PRIORITY)
    .setUncaughtExceptionHandler((t, e) -> {
        System.err.println("线程" + t.getName() + "发生未捕获异常: " + e.getMessage());
        e.printStackTrace();
    })
    .build();

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    5, 10, 60, TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(100),
    factory);

线程池监控与 JMX 集成

在生产环境中,可以通过 JMX 监控线程池状态,方便运维人员查看和调整:

import javax.management.*;
import java.lang.management.ManagementFactory;
import java.util.concurrent.*;

public class JmxMonitorableThreadPool {
    public static class ThreadPoolMonitor implements DynamicMBean {
        private final ThreadPoolExecutor executor;

        public ThreadPoolMonitor(ThreadPoolExecutor executor) {
            this.executor = executor;
        }

        @Override
        public Object getAttribute(String attribute) throws AttributeNotFoundException,
                MBeanException, ReflectionException {
            switch (attribute) {
                case "CorePoolSize": return executor.getCorePoolSize();
                case "MaximumPoolSize": return executor.getMaximumPoolSize();
                case "ActiveThreadCount": return executor.getActiveCount();
                case "PoolSize": return executor.getPoolSize();
                case "QueueSize": return executor.getQueue().size();
                case "CompletedTaskCount": return executor.getCompletedTaskCount();
                case "TaskCount": return executor.getTaskCount();
                default: throw new AttributeNotFoundException("Unknown attribute: " + attribute);
            }
        }

        @Override
        public void setAttribute(Attribute attribute) throws AttributeNotFoundException,
                InvalidAttributeValueException, MBeanException, ReflectionException {
            String name = attribute.getName();
            Object value = attribute.getValue();

            if ("CorePoolSize".equals(name) && value instanceof Integer) {
                executor.setCorePoolSize((Integer) value);
            } else if ("MaximumPoolSize".equals(name) && value instanceof Integer) {
                executor.setMaximumPoolSize((Integer) value);
            } else {
                throw new AttributeNotFoundException("Attribute " + name + " not found or not writable");
            }
        }

        @Override
        public AttributeList getAttributes(String[] attributes) {
            AttributeList list = new AttributeList();
            for (String attribute : attributes) {
                try {
                    list.add(new Attribute(attribute, getAttribute(attribute)));
                } catch (Exception e) {
                    // 忽略无法获取的属性
                }
            }
            return list;
        }

        @Override
        public AttributeList setAttributes(AttributeList attributes) {
            AttributeList result = new AttributeList();
            for (Object o : attributes) {
                Attribute attr = (Attribute) o;
                try {
                    setAttribute(attr);
                    result.add(new Attribute(attr.getName(), getAttribute(attr.getName())));
                } catch (Exception e) {
                    // 忽略无法设置的属性
                }
            }
            return result;
        }

        @Override
        public Object invoke(String actionName, Object[] params, String[] signature)
                throws MBeanException, ReflectionException {
            if ("shutdown".equals(actionName) && (params == null || params.length == 0)) {
                executor.shutdown();
                return null;
            } else if ("shutdownNow".equals(actionName) && (params == null || params.length == 0)) {
                return executor.shutdownNow();
            } else if ("prestartAllCoreThreads".equals(actionName) && (params == null || params.length == 0)) {
                return executor.prestartAllCoreThreads();
            }
            throw new ReflectionException(new NoSuchMethodException(actionName));
        }

        @Override
        public MBeanInfo getMBeanInfo() {
            MBeanAttributeInfo[] attributes = new MBeanAttributeInfo[] {
                new MBeanAttributeInfo("CorePoolSize", "int", "核心线程数", true, true, false),
                new MBeanAttributeInfo("MaximumPoolSize", "int", "最大线程数", true, true, false),
                new MBeanAttributeInfo("ActiveThreadCount", "int", "活跃线程数", true, false, false),
                new MBeanAttributeInfo("PoolSize", "int", "当前线程池大小", true, false, false),
                new MBeanAttributeInfo("QueueSize", "int", "队列中等待任务数", true, false, false),
                new MBeanAttributeInfo("CompletedTaskCount", "long", "已完成任务数", true, false, false),
                new MBeanAttributeInfo("TaskCount", "long", "总任务数", true, false, false),
            };

            MBeanOperationInfo[] operations = new MBeanOperationInfo[] {
                new MBeanOperationInfo("shutdown", "关闭线程池", null, "void", MBeanOperationInfo.ACTION),
                new MBeanOperationInfo("shutdownNow", "立即关闭线程池", null, "java.util.List", MBeanOperationInfo.ACTION),
                new MBeanOperationInfo("prestartAllCoreThreads", "预启动所有核心线程", null, "int", MBeanOperationInfo.ACTION),
            };

            return new MBeanInfo(
                getClass().getName(),
                "线程池监控和管理",
                attributes,
                null,  // 构造函数
                operations,
                null); // 通知
        }
    }

    public static ThreadPoolExecutor createMonitoredThreadPool(
            String poolName, int coreSize, int maxSize, int queueCapacity) throws Exception {

        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                coreSize, maxSize,
                60, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(queueCapacity));

        // 注册MBean
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
        ObjectName name = new ObjectName("com.example:type=ThreadPool,name=" + poolName);

        ThreadPoolMonitor monitor = new ThreadPoolMonitor(executor);
        mbs.registerMBean(monitor, name);

        System.out.println("线程池 " + poolName + " 已创建并注册到JMX");
        return executor;
    }

    // 使用示例
    public static void main(String[] args) throws Exception {
        ThreadPoolExecutor executor = createMonitoredThreadPool("业务线程池", 5, 10, 100);

        // 提交一些任务测试
        for (int i = 0; i < 20; i++) {
            final int taskId = i;
            executor.submit(() -> {
                try {
                    System.out.println("执行任务: " + taskId);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                return taskId;
            });
        }

        // 此时可以通过JMX客户端(如JConsole或VisualVM)连接并查看/修改线程池参数
        System.out.println("线程池已启动,可通过JMX客户端(如JConsole)连接查看");
        System.out.println("按Enter键退出");
        System.in.read();

        executor.shutdown();
    }
}

通过 JMX,我们可以:

  1. 实时监控线程池状态
  2. 动态调整核心线程数和最大线程数
  3. 执行关闭等操作
  4. 集成到监控系统(如 Prometheus、Grafana)实现自动化监控和告警

九、总结

下面用表格总结一下关于 Java 线程池核心线程数动态调整的要点:

要点

说明

是否支持运行时修改

是,ThreadPoolExecutor 支持通过 setCorePoolSize()方法动态修改

增加核心线程数的生效时机

如队列中有等待任务,会立即创建新线程;否则等新任务到来时创建

减少核心线程数的生效时机

默认情况下核心线程不会被终止;设置 allowCoreThreadTimeOut(true)后,多余线程在空闲超时后被回收

线程池状态影响

RUNNING 状态可完全调整;SHUTDOWN 状态可调整但不会创建新线程;STOP 及之后的状态调整无效

prestartAllCoreThreads 作用

预启动所有核心线程,减少任务首次执行延迟;调整核心线程数后可立即创建新增线程

队列类型影响

无界队列导致 maximumPoolSize 失效;有界队列与核心线程数共同控制并发

线程安全性

setCorePoolSize 本身线程安全,但并发调整建议通过同步机制或单线程调度器控制

应用场景

日夜负载差异大的系统、流量有波峰的系统、需要自适应调整的系统

调整决策依据

队列长度、活跃线程数、CPU 利用率、任务吞吐量、平均处理时间

监控方式

JMX、Micrometer、Prometheus 等监控框架,结合自定义指标

调优建议

结合 keepAliveTime、队列容量、拒绝策略整体调优;避免频繁调整导致线程创建销毁开销

线程池核心线程数的动态调整是 Java 并发编程中的一个强大特性,合理使用可以让系统更好地适应负载变化,提高资源利用率和系统吞吐量。掌握这项技术,能让你的系统在面对不同负载时更加灵活高效!

复习并发编程的基础知识之线程池及线程池的核心线程数设置 workQueue:the queue to use for holding tasks before they are executed.这个队列用于存放任务,什么样的任务呢?在这些任务被执行之前的任务。也就是说,任务没执行的时候都放在这个阻塞队列中。unit:和keepAliveTime成对出现,存活时间的单位。其中线程池的几个重要参数是面试中经常被问的内容。threadFactory:线程工厂。线程池中的线程对象–》银行的服务窗口。在java中我们在使用线程池的时候,handler:拒绝策略。 阅读详情

相关推荐

OpenCompass实战:从零部署大模型评测平台,量化模型能力选型

在大模型技术选型与评估中,客观、可量化的评测体系是工程实践的关键。其核心原理在于通过标准化的数据集、统一的评测方法与自动化流程,将主观的模型体验转化为可比较的指标数据。这种评测框架的技术价值在于解决了模型能力评估的模糊性问题,为开发者提供了模型选型、效果对比与迭代优化的科学依据。典型的应用场景包括对比不同开源模型在代码生成、逻辑推理等特定任务上的性能,或是评估微调后模型在业务数据集上的提升效果。OpenCompass作为开源的大模型全能力评测平台,正是这一理念的工程化实现。它通过模块化的四层流水线架构和配置

weixin_28725037的博客 626

Java线程池ThreadPoolExecutor的7个参数详解

下面是对的七个参数的详细解释:核心线程数(corePoolSize):核心线程数是线程池中保持活动状态的线程数。即使没有任务需要执行,核心线程也不会被回收。当有新任务提交时,如果核心线程都在忙碌,则会创建新的线程来处理任务。最大线程数(maximumPoolSize):最大线程数是线程池中允许的最大线程数。当工作队列满了并且活动线程数达到最大线程数时,如果还有新任务提交,线程池将创建新的线程来处理任务。但是,超过最大线程数的线程可能会导致资源消耗过大。

学亮编程手记 4400

【鸿蒙实战开发】HarmonyOS申请调试签名证书过程

这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。

HarmonyOS_002的博客 3561

【技术应用】java实现动态线程池ThreadPoolExecutor

java实现动态线程池ThreadPoolExecutor,代码示例,开源的动态可监控线程池框架(DynamicTp)推荐

dylan的博客 1902

图像去雾常见数据集

上述数据集涵盖了室内、室外、真实和合成等多种场景,可以满足不同研究需求。在选择数据集时,建议根据具体任务的应用场景和目标选择合适的数据集,例如真实雾天图像适合模型的实际应用验证,而合成数据则适合模型的快速迭代和训练。希望本文能为从事图像去雾研究的朋友提供一些帮助!

m0_68604571的博客 6334

深入解析Vortex GPGPU cache设计(2),关于cache_bank

本文分析了Vortex处理器的cache_bank模块设计,作为cache系列的第二部分。文章详细阐述了cache_bank的基本结构,包括地址位分配和默认配置参数。重点解析了cache的5种操作及其优先级。文章详细介绍了二级流水线设计,包括TAG/DATARAM的读写操作时序。

weixin_55313207的博客 1168

Java线程池核心线程数设置

Java线程池核心线程数设置

qq_41139119的博客 2334

大麦网抢票协议逆向分析:从Web安全到高并发风控实战

在当今高并发Web应用场景下,理解网络协议交互与反爬虫机制是后端开发和系统架构设计的核心技能。其基本原理涉及客户端与服务器之间通过HTTP/HTTPS协议进行数据交换,关键环节包括请求参数构造、身份认证与会话管理。这一技术的核心价值在于保障系统安全与公平性,通过动态令牌、签名算法及设备指纹等多重手段,有效抵御自动化脚本攻击。典型应用场景包括票务系统、电商秒杀等需要严格管控资源访问的高并发业务。本文以热门票务平台为例,深入剖析其**请求链与令牌体系**及**行为生物特征分析**等风控策略,通过实战演示协议逆向

weixin_34354173的博客 453

Java 线程池及参数动态调节详解

前前言:本文搬自头条作者:why技术 前言:曾经自诩对线程池了如指掌,不料看了美团的一篇技术文章后才知道原来线程池的参数还可以动态调节。 经典面试题 在这篇文章中我主要回答上面抛出的这个问题:你这几个参数的值怎么来的呀? 要回答这个问题,我们得先说说这几个参数是什么,请看截图: 其实,官方的注释写的都非常明白了。你看文章的时一定要结合英文,因为英文是 Doug Lea(...

liu_ares的博客 8375

【AUTOSAR OS】调度表管理模块深度解析

本文深入解析AUTOSAR OS调度表的实现机制。调度表通过预定义到期点序列控制任务激活时序,支持周期性执行、多核协同和容错处理。核心数据结构包括调度表控制块(STCB)、配置结构和到期点动作。关键函数涵盖初始化、启动、到期点处理及链表管理,采用O(n)时间复杂度。以发动机控制为例展示配置与使用方式,并探讨显式同步、时间容错等高级特性。最后提出EP数量控制、链表优化等性能建议,为汽车ECU时间触发系统开发提供参考。

1606

YOLOv8改进-利用图像去雾网络UnfogNet提升检测精度的探索【附核心模块代码】

YOLOv8-UnfogNet联合模型的提出为目标检测和图像去雾领域提供了一个新的思路。通过将图像去雾网络和目标检测网络结合,不仅可以提升在恶劣天气下的目标检测精度,还能够为实际应用中的自动驾驶、监控安防等领域带来更强的鲁棒性和适应性。随着去雾技术和目标检测算法的不断发展,我们相信,这种联合方法将在多个领域中获得更加广泛的应用,并为进一步提升图像质量和检测精度做出重要贡献。

一键难忘的博客 3202

正在运行的线程池,如何动态修改核心线程数?

下面我们来了解线程池的核心参数都有哪些? corePoolSize:表示核心线程池的大小。当提交一个任务时,如果当前核心线程池的线程个数没有达到 corePoolSize,则会创建新的线程来执行所提交的任务,即使当前核心线程池有空闲的线程。如果当前核心线程池的线程个数已经达到了 corePoolSize,则不再重新创建线程。如果调用了prestartCoreThread()或者 prestartAllCoreThreads(),线程池创建的时候所有的核心线程都会被创建并且启动。 maximumPoolS

养歌的博客 7464

2022年8月27日全国青少年信息素养大赛Python编程小学组决赛真题+答案解析

2022年8月27日全国青少年信息素养大赛Python编程小学组决赛真题+答案解析

伶俐角少儿编程 454

java基础: Java线程池核心线程数动态调整机制深度解析

Java线程池核心线程数的动态调整是高性能Java应用的必备技能。技术上:通过setCorePoolSize实现动态调整,但需要考虑线程安全、状态同步等复杂问题算法上:需要结合控制系统理论、机器学习等构建智能调整策略工程上:必须建立完善的监控、告警和回滚机制在阿里巴巴双11和字节跳动大型活动保障中,这种动态调整技术帮助我们在保证系统稳定的同时,实现了资源利用的最大化。建议开发者在理解原理的基础上,结合实际业务场景进行调优实践。

weixin_43290370的博客 1229

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Java线程池核心线程数动态修改完全指南:原理、方法与实战

核心结论✅ Java线程池的核心线程数和最大线程数可以在运行时动态修改通过和方法实现提升核心线程数时立即创建新线程处理等待任务降低核心线程数时空闲超时后回收,不影响正在执行的任务队列和线程工厂不支持动态修改,需提前规划生产环境建议结合配置中心(Nacos/Apollo)实现参数动态推送底部锚点⬆ ⬆ 顶部 ⬆ ⬆⬇ ⬇ 底部 ⬇ ⬇⬆ ⬆ 顶部 ⬆ ⬆。

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 112

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Java 线程池调优实战:核心线程数在运行中如何动态修改?

维度核心内容能否修改✅ 可以,使用增大逻辑按需创建线程处理队列中的任务减小逻辑空闲线程逐步回收,不影响执行中的任务配套方法最佳实践CPU 密集型:n+1;IO 密集型:2n生产建议结合配置中心实现动态推送,结合监控指标自动调整一句话总结允许运行时动态调整核心线程数——增大时会按需创建线程处理积压任务,减小时空闲线程逐步回收,是实现线程池弹性伸缩的核心 API。欢迎在评论区分享你在生产环境中动态调整线程池参数的经验!底部锚点⬆ ⬆ 顶部 ⬆ ⬆⬇ ⬇ 底部 ⬇ ⬇⬆ ⬆ 顶部 ⬆ ⬆。

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 1898

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

线程池核心线程数和最大线程数总结

核心线程数配置个数:看IO密集型,还是CPU密集型 (1)一般平时cpu使用率4%以下,都是IO密集型,IO密集型具体看实践,目前项目里核心线程数设置50,最大线程数可以和核心线程数相同,队列配置大一些,使永远触发不到最大线程数 (2)如果是大量计算CPU使用率过高,属于CPU密集型,CPU密集型以4C8G为例,核心线程数一般设置4,最大线程数可以和核心线程数相同,队列配置大一些,使永远触发不到最大线程数 核心线程数永远不会销毁,和线程池生命周期一样, 除非核心线程shutdown ...

qq_34486648的博客 2万+

线程池如何确定核心线程数

通过性能监控工具(如 VisualVM、JConsole)分析任务的 CPU 和 I/O 使用情况,从而优化核心线程数。线程池的核心线程数是影响并发性能的重要参数,合理的配置可以提高任务处理效率,降低资源浪费。I/O 密集型任务涉及大量的 I/O 操作,如网络请求、数据库访问、文件读写等。核心线程数是线程池中的一个概念,用于定义线程池的基本线程数量。在某些场景中(如高并发的 Web 服务器),线程池的任务量可能会动态变化,此时可以使用。合理的核心线程数可以显著提高系统性能,同时避免资源浪费。

Flying_Fish_roe的博客 1506

JAVA线程池监控以及动态调整线程池

Java线程池源码分析里虽然介绍了线程池的核心配置(核心线程数、最大线程数和队列大小)该如何配置,但是实际上业界也没有一个统一的标准。虽然有些所谓的"公式",但是不同的业务场景复杂多变,配置原则也不尽相同。从实际经验来看,IO密集型、CPU密集型应用在线程配置上就比较悬殊,因此没有一个通用的适合所有场景的公式。

weixin_54828627的博客 5509

java 动态线程池_线程池的参数动态调整

经典面试题这次的文章还是绕回了我写的第三篇原创文章《有的线程它死了,于是它变成一道面试题》中留下的几个问题:哎,兜兜转转,走走停停。天道好轮回,苍天饶过谁?在这篇文章中我主要回答上面抛出的这个问题:你这几个参数的值怎么来的呀?要回答这个问题,我们得先说说这几个参数是什么,请看截图:其实,官方的注释写的都非常明白了。你看文章的时一定要结合英文,因为英文是 Doug Lea(作者)他自己写的,表达的是...

weixin_36078604的博客 3911

Java线程池参数详解

线程池是现代并发编程中不可或缺的工具,合理配置线程池参数能够显著提升应用的性能和稳定性。本文将深入剖析线程池的核心参数,包括核心线程数、最大线程数、线程存活时间、任务队列类型及拒绝策略等,结合实际案例帮助读者理解每个参数的作用及调优思路。

2301_80795057的博客 2万+

如何合理地设置 Java 线程池的线程数?

总结来说,合理设置线程数需要平衡 CPU、内存和任务特性,既要避免线程过少导致任务积压,也要避免过多导致资源浪费。它不仅是线程池配置的核心问题,还与其他并发优化技术紧密相连,是性能调优的重要环节。线程数的设置直接影响线程池的工作流程(如线程创建、任务排队、拒绝策略触发),是原理的实践体现。线程数与队列容量密切相关,队列过小可能导致线程频繁扩容,队列过大可能浪费内存。)无需手动设置线程数,JVM 自动管理,但在传统线程池中需仔细计算。在 Java 中,合理设置线程池的线程数(包括。动态调整线程数的能力(如。

qq_63553317的博客 1811

Java 线程池的线程数,这样设置更高效!

设置线程池大小是一个需要根据实际情况进行调整的过程。没有一个通用的公式可以适用于所有场景。关键是要理解任务的类型、CPU 核心数、任务的平均执行时间、任务的提交频率等因素,并结合监控数据进行动态调整。

qq_56158663的博客 2214

线程池最佳核心线程数该如何确定

线程池最佳核心线程数该如何确定

weixin_45817985的博客 1564
上一篇: Java 并发利器:CyclicBarrier 从入门到精通
下一篇: 面试官问:MySQL 为什么不能用 Docker 部署吗?答错直接挂!
程序员职业指南
博客等级 码龄4年 2136粉丝 960原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值