博客
关于我
spring自定义线程池 逻辑 配置 ThreadPoolTaskExecutor corePoolSize maxPoolSize queueCapacity rejectedExecutionHa
阅读量:797 次
发布时间:2023-02-26

本文共 4875 字,大约阅读时间需要 16 分钟。

Spring自定义线程池配置与使用指南

线程池概述

线程池是Java中一个核心的并发处理机制,主要用于高效管理和调度线程资源。它能够最大化地利用系统资源,同时避免因过度创建线程而引发的性能问题。Spring框架内置了丰富的线程池功能,允许开发者灵活配置和管理线程池,适用于不同的业务场景。

线程池配置参数

线程池的核心配置参数包括核心线程池大小 (corePoolSize)、最大线程池大小 (maxPoolSize)、任务队列容量 (queueCapacity)、线程空闲存活时间 (keepAliveSeconds)、任务等待终止时间 (awaitTerminationSeconds) 和线程名称前缀 (threadNamePrefix)。

线程池调用逻辑

线程池的逻辑分为以下几个方面:

  • 动态值管理corePoolSizequeueCapacity 在程序运行时是一个动态值。
  • 线程创建机制
    • 当线程池未达到核心线程数时,新任务会创建新的线程。
    • 当线程池已达到核心线程数但存在空闲线程时,会复用空闲线程执行任务。
    • 当线程池已达到最大线程数且无空闲线程时,新任务会被拒绝(默认策略是抛出异常)。
  • 任务队列管理:使用阻塞队列,先进先出,保证任务高效执行。
  • 线程终止机制:当任务完成后,线程会优先销毁超过核心线程数的线程,空闲线程根据 keepAliveSeconds 定时销毁。
  • 线程池状态监控:通过 getActiveCount()getPoolSize() 可以判断线程池是否有空闲线程。
  • 线程池参数配置建议

  • 核心线程池大小 (corePoolSize):建议根据业务需求设置合理的线程数,默认值为1。
  • 最大线程池大小 (maxPoolSize):默认值为无限,建议根据硬件资源限制设置上限。
  • 任务队列容量 (queueCapacity):默认值为无限,建议根据任务吞吐量设置合理值。
  • 线程空闲存活时间 (keepAliveSeconds):默认值为60秒,建议根据业务场景调整。
  • 任务等待终止时间 (awaitTerminationSeconds):默认值为180秒,建议根据业务需要调整。
  • 线程池代码实现

    核心配置类

    @Data
    @NoArgsConstructor
    public class ThreadPoolConfig {
    private int corePoolSize = 1;
    private int maxPoolSize = Integer.MAX_VALUE;
    private int keepAliveSeconds = 60;
    private int queueCapacity = Integer.MAX_VALUE;
    private int awaitTerminationSeconds = 180;
    private String threadNamePrefix = "ThreadPoolConfig";
    private boolean allowCoreThreadTimeOut = true;
    }

    线程池配置类

    @Configuration
    public class ThreadPool {
    @Bean(name = "customDefaultThreadPool")
    public Executor customDefaultThreadPool() {
    ThreadPoolConfig config = new ThreadPoolConfig(10, 20, "customDefaultThreadPool");
    return customThreadPool(config);
    }
    @Bean(name = "receiveOrderThreadPool")
    public Executor receiveOrderThreadPool() {
    ThreadPoolConfig config = new ThreadPoolConfig(20, 50, "receiveOrderThreadPool");
    return customThreadPool(config);
    }
    @Bean(name = "handlerOrderThreadPool")
    public Executor handlerOrderThreadPool() {
    ThreadPoolConfig config = new ThreadPoolConfig(10, 20, "handlerOrderThreadPool");
    return customThreadPool(config);
    }
    private Executor customThreadPool(ThreadPoolConfig config) {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(config.getCorePoolSize());
    executor.setMaxPoolSize(config.getMaxPoolSize());
    executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
    executor.setQueueCapacity(config.getQueueCapacity());
    executor.setAllowCoreThreadTimeOut(config.isAllowCoreThreadTimeOut());
    executor.setThreadNamePrefix(config.getThreadNamePrefix());
    executor.setAwaitTerminationSeconds(config.getAwaitTerminationSeconds());
    executor.setWaitForTasksToCompleteOnShutdown(Boolean.TRUE);
    executor.initialize();
    return executor;
    }
    }

    业务异步执行

    @Component
    public class OrderComponent {
    @Async("customDefaultThreadPool")
    public void testDefaultThreadPool(Integer i) {
    log.info("默认线程池-开始:索引-{}", i);
    try {
    Thread.sleep(1000L);
    log.info("默认线程池-结束:索引-{}", i);
    } catch (InterruptedException e) {
    log.error("睡眠线程异常:{}", e.toString());
    }
    }
    @Async("receiveOrderThreadPool")
    public void testReceiveOrderThreadPool(Integer i) {
    log.info("接单线程池-开始:索引-{}", i);
    try {
    Thread.sleep(1000L);
    log.info("接单线程池-结束:索引-{}", i);
    } catch (InterruptedException e) {
    log.error("睡眠线程异常:{}", e.toString());
    }
    }
    @Async("handlerOrderThreadPool")
    public void testHandlerOrderThreadPool(Integer i) {
    log.info("处理订单线程池-开始:索引-{}", i);
    try {
    Thread.sleep(1000L);
    log.info("处理订单线程池-结束:索引-{}", i);
    } catch (InterruptedException e) {
    log.error("睡眠线程异常:{}", e.toString());
    }
    }
    }

    线程池使用与优化

    动态管理

    通过 ThreadPoolTaskExecutor 可以动态修改线程池参数,例如:

    @Autowired
    @Lazy
    private ThreadPoolTaskExecutor customDefaultThreadPool;
    public String testThreadPool(int forEachNum) {
    try {
    int activeCount = customDefaultThreadPool.getActiveCount();
    int corePoolSize = customDefaultThreadPool.getPoolSize();
    System.out.println("customDefault activeCount: " + activeCount);
    System.out.println("customDefault corePoolSize: " + corePoolSize);
    for (Integer i = 1; i <= forEachNum; i++) {
    try {
    orderComponent.testDefaultThreadPool(i);
    } catch (RejectedExecutionException e) {
    return "线程资源不够用, 拒绝执行任务,请稍后重试";
    }
    }
    return "success";
    } catch (Exception e) {
    return "";
    }
    }

    性能优化建议

  • 合理配置线程池参数:根据业务需求和硬件资源合理配置 corePoolSizemaxPoolSizequeueCapacity
  • 设置合理的空闲存活时间:根据业务场景调整 keepAliveSeconds,避免资源浪费。
  • 及时终止线程池:建议设置合理的 awaitTerminationSeconds,避免线程资源耗尽。
  • 监控线程池状态:定期检查线程池状态,及时发现和处理异常情况。
  • 通过合理配置和使用Spring自定义线程池,可以有效地管理并发任务,优化系统性能。

    转载地址:http://tbvfk.baihongyu.com/

    你可能感兴趣的文章
    Oracle重置序列(不删除重建方式)
    查看>>
    Oracle闪回技术(Flashback)
    查看>>
    oracle零碎要点---ip地址问题,服务问题,系统默认密码问题
    查看>>
    oracle零碎要点---oracle em的web访问地址忘了
    查看>>
    Oracle零碎要点---多表联合查询,收集数据库基本资料
    查看>>
    Oracle静默安装
    查看>>
    【Bert101】变压器模型背后的复杂数学【02/4】
    查看>>
    Oracle面试题:Oracle中truncate和delete的区别
    查看>>
    ThreadLocal线程内部存储类
    查看>>
    thinkphp 常用SQL执行语句总结
    查看>>
    Oracle:ORA-00911: 无效字符
    查看>>
    Text-to-Image with Diffusion models的巅峰之作:深入解读 DALL·E 2
    查看>>
    Tensorflow.python.framework.errors_impl.ResourceExhaustedError:无法分配内存[操作:AddV2]
    查看>>
    TCP基本入门-简单认识一下什么是TCP
    查看>>
    tableviewcell 中使用autolayout自适应高度
    查看>>
    Symbolic Aggregate approXimation(SAX,符号聚合近似)介绍-ChatGPT4o作答
    查看>>
    Orcale表被锁
    查看>>
    svn访问报错500
    查看>>
    sum(a.YYSR) over (partition by a.hy_dm) 不需要像group by那样需要分组函数。方便。
    查看>>
    ORCHARD 是什么?
    查看>>