SpringBoot 线程池 配置使用详解

一、核心特性

Springboot 集成
支持 @Async 注解,简化异步方法调用。
参数可配置化

核心线程数、最大线程数、队列容量、拒绝策略等均可通过配置调整。
生命周期管理

实现 Lifecycle 接口,支持线程池的启动和关闭(如应用关闭时优雅终止任务)。
任务装饰器

支持通过 TaskDecorator 对任务进行装饰(如传递上下文信息)

二、添加依赖

pom.xml 文件中添加 Spring Boot Starter AOP 依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

三、参数详解

通过 Spring 配置文件或 @Bean 定义线程池时,需设置以下关键参数:

参数名称说明默认值
corePoolSize核心线程数,即使空闲也不会被回收1
maxPoolSize最大线程数,当队列满时创建新线程直到达到此值Integer.MAX_VALUE
queueCapacity任务队列容量(使用 LinkedBlockingQueue 或 ArrayBlockingQueue)Integer.MAX_VALUE
keepAliveSeconds非核心线程的空闲存活时间(秒)60
threadNamePrefix线程名前缀,便于日志追踪"task-executor-"
allowCoreThreadTimeOut是否允许核心线程超时回收false
rejectedExecutionHandler拒绝策略(如 AbortPolicy、CallerRunsPolicy)AbortPolicy(直接抛出异常)

四、配置线程池

@Configuration
@EnableAsync
public class ExecutorConfig {private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class);@Value("${async.executor.thread.core_pool_size}")private int corePoolSize;@Value("${async.executor.thread.max_pool_size}")private int maxPoolSize;@Value("${async.executor.thread.queue_capacity}")private int queueCapacity;@Value("${async.executor.thread.name.prefix}")private String namePrefix;@Bean(name = "asyncServiceExecutor")public Executor asyncServiceExecutor() {logger.info("start asyncServiceExecutor");ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();//配置核心线程数executor.setCorePoolSize(corePoolSize);//配置最大线程数executor.setMaxPoolSize(maxPoolSize);//配置队列大小executor.setQueueCapacity(queueCapacity);//配置线程池中的线程的名称前缀executor.setThreadNamePrefix(namePrefix);// rejection-policy:当pool已经达到max size的时候,如何处理新任务// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());//执行初始化executor.initialize();return executor;}
}

@Value是我配置在 application.yml,可以参考配置,自由定义 

# 异步线程配置
# 配置核心线程数
async.executor.thread.core_pool_size = 5
# 配置最大线程数
async.executor.thread.max_pool_size = 5
# 配置队列大小
async.executor.thread.queue_capacity = 99999
# 配置线程池中的线程的名称前缀
async.executor.thread.name.prefix = async-service-

五、应用实践

1、异步任务处理

创建一个服务类 AsyncService,并在其方法上使用 @Async 注解来定义异步任务:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;@Service
public class AsyncService {private static final Logger logger = LoggerFactory.getLogger(AsyncService.class);@Async("taskExecutor")public void asyncTask(String taskName) {logger.info(Thread.currentThread().getName() + " 开始执行任务: " + taskName);try {Thread.sleep(2000); // 模拟耗时操作} catch (InterruptedException e) {Thread.currentThread().interrupt();logger.error("任务执行被中断", e);} finally {logger.info(Thread.currentThread().getName() + " 任务执行完成: " + taskName);}}
}

创建一个控制器类 AsyncController,用于触发异步任务(线程安全的)

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.concurrent.Future;@RestController
public class AsyncController {private static final Logger logger = LoggerFactory.getLogger(AsyncController.class);@Autowiredprivate AsyncService asyncService;@GetMapping("/trigger")public String triggerAsyncTasks() {logger.info("开始触发异步任务");for (int i = 0; i < 10; i++) {asyncService.asyncTask("任务 " + i);}return "异步任务已触发";}
}

创建一个监控组件 ThreadPoolMonitor,用于定期监控线程池的状态

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;@Component
public class ThreadPoolMonitor {private static final Logger logger = LoggerFactory.getLogger(ThreadPoolMonitor.class);@Autowiredprivate ThreadPoolTaskExecutor taskExecutor;@Scheduled(fixedRate = 60000) // 每分钟执行一次public void monitorThreadPool() {int activeCount = taskExecutor.getActiveCount();int poolSize = taskExecutor.getPoolSize();int corePoolSize = taskExecutor.getCorePoolSize();int maxPoolSize = taskExecutor.getMaxPoolSize();int queueSize = taskExecutor.getThreadPoolExecutor().getQueue().size();int completedTaskCount = taskExecutor.getThreadPoolExecutor().getCompletedTaskCount();logger.info("线程池状态 - 活动线程数: {}, 当前线程数: {}, 核心线程数: {}, 最大线程数: {}, 队列大小: {}, 已完成任务数: {}",activeCount, poolSize, corePoolSize, maxPoolSize, queueSize, completedTaskCount);// 检查线程池是否接近饱和if (activeCount >= maxPoolSize * 0.8 || queueSize >= taskExecutor.getQueueCapacity() * 0.8) {logger.warn("线程池负载过高!请考虑优化配置或检查任务执行情况");}}
}

 确保在启动类上添加 @EnableAsync 注解,以启用异步任务支持

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;@SpringBootApplication
@EnableAsync
public class AsyncDemoApplication {public static void main(String[] args) {SpringApplication.run(AsyncDemoApplication.class, args);}
}

测试:

启动 Spring Boot 应用后,访问 http://localhost:8080/trigger,即可看到异步任务在线程池中执行的情况,同时线程池的状态也会定期输出到日志中。

代码说明

  • @EnableAsync 注解 :用于启用 Spring 的异步方法执行支持,确保 Spring 容器能够识别和处理带有 @Async 注解的方法。

  • @Async 注解 :用于标注希望异步执行的方法,需指定所使用的线程池 Bean 的名称,在本例中为 “taskExecutor”。当该方法被调用时,Spring 会将其提交到指定的线程池中执行。

  • ThreadPoolTaskExecutor :是 Spring 提供的一个线程池任务执行器,通过设置核心线程数、最大线程数、队列容量等参数,可以根据应用的需求灵活地配置线程池。

  • 异步任务失败处理 :通过自定义的拒绝策略,在线程池满时记录详细信息并抛出异常,以便及时发现任务执行失败的情况。

  • 线程池监控 :使用 @Scheduled 注解定期监控线程池的状态,包括活动线程数、当前线程数、核心线程数、最大线程数、队列大小和已完成任务数等,帮助开发者了解线程池的运行情况,以便及时进行优化和调整

2、高并发请求处理

在 Web 应用中处理大量并发请求,避免阻塞主线程

@RestController
public class MyController {@Autowiredprivate ThreadPoolTaskExecutor taskExecutor;@GetMapping("/process")public CompletableFuture<String> handleRequest() {return CompletableFuture.supplyAsync(() -> {// 耗时操作return "Result";}, taskExecutor);}}

3、定时任务调度

@EnableScheduling
@Configuration
public class SchedulerConfig {@Beanpublic ThreadPoolTaskScheduler taskScheduler() {ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();scheduler.setPoolSize(5);scheduler.setThreadNamePrefix("Scheduler-");return scheduler;}}@Service
public class ScheduledService {@Scheduled(fixedRate = 5000)public void scheduledTask() {// 定时任务逻辑}}

 

拒绝策略(Rejected Policies

当线程池和队列均满时,处理新任务的策略:

策略类行为描述
AbortPolicy直接抛出 RejectedExecutionException(默认)
CallerRunsPolicy由提交任务的线程直接执行任务(同步阻塞提交者)
DiscardPolicy静默丢弃新任务,不抛异常
DiscardOldestPolicy丢弃队列中最旧的任务,然后重试提交新任务

如下给出不同拒绝策略的配置类,请结合上面的配置类整合使用

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;@Configuration
public class ThreadPoolConfig {@Bean(name = "abortPolicyExecutor")public ThreadPoolTaskExecutor abortPolicyExecutor() {return createExecutor(new ThreadPoolExecutor.AbortPolicy());}@Bean(name = "callerRunsPolicyExecutor")public ThreadPoolTaskExecutor callerRunsPolicyExecutor() {return createExecutor(new ThreadPoolExecutor.CallerRunsPolicy());}@Bean(name = "discardPolicyExecutor")public ThreadPoolTaskExecutor discardPolicyExecutor() {return createExecutor(new ThreadPoolExecutor.DiscardPolicy());}@Bean(name = "discardOldestPolicyExecutor")public ThreadPoolTaskExecutor discardOldestPolicyExecutor() {return createExecutor(new ThreadPoolExecutor.DiscardOldestPolicy());}private ThreadPoolTaskExecutor createExecutor(ThreadPoolExecutor.RejectedExecutionHandler rejectedExecutionHandler) {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5); // 核心线程数executor.setMaxPoolSize(10); // 最大线程数executor.setQueueCapacity(100); // 队列容量executor.setThreadNamePrefix("Task-Executor-"); // 线程名前缀executor.setRejectedExecutionHandler(rejectedExecutionHandler);executor.initialize();return executor;}
}

创建一个服务类 TaskService,用于执行任务

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;@Service
public class TaskService {@Async("abortPolicyExecutor")public void executeWithAbortPolicy(String taskName) {executeTask(taskName);}@Async("callerRunsPolicyExecutor")public void executeWithCallerRunsPolicy(String taskName) {executeTask(taskName);}@Async("discardPolicyExecutor")public void executeWithDiscardPolicy(String taskName) {executeTask(taskName);}@Async("discardOldestPolicyExecutor")public void executeWithDiscardOldestPolicy(String taskName) {executeTask(taskName);}private void executeTask(String taskName) {try {System.out.println(Thread.currentThread().getName() + " 开始执行任务: " + taskName);Thread.sleep(2000); // 模拟任务执行时间System.out.println(Thread.currentThread().getName() + " 任务执行完成: " + taskName);} catch (InterruptedException e) {Thread.currentThread().interrupt();System.err.println("任务执行被中断: " + taskName);}}
}

创建一个控制器类 TaskController,用于触发任务执行

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class TaskController {@Autowiredprivate TaskService taskService;@GetMapping("/trigger/abort")public String triggerAbortPolicy(@RequestParam String taskName) {taskService.executeWithAbortPolicy(taskName);return "任务已提交到使用 AbortPolicy 的线程池";}@GetMapping("/trigger/caller")public String triggerCallerRunsPolicy(@RequestParam String taskName) {taskService.executeWithCallerRunsPolicy(taskName);return "任务已提交到使用 CallerRunsPolicy 的线程池";}@GetMapping("/trigger/discard")public String triggerDiscardPolicy(@RequestParam String taskName) {taskService.executeWithDiscardPolicy(taskName);return "任务已提交到使用 DiscardPolicy 的线程池";}@GetMapping("/trigger/discardoldest")public String triggerDiscardOldestPolicy(@RequestParam String taskName) {taskService.executeWithDiscardOldestPolicy(taskName);return "任务已提交到使用 DiscardOldestPolicy 的线程池";}
}

启动 Spring Boot 应用后,分别访问以下 URL 来测试不同拒绝策略的行为:

  • http://localhost:8080/trigger/abort?taskName=任务1

  • http://localhost:8080/trigger/caller?taskName=任务2

  • http://localhost:8080/trigger/discard?taskName=任务3

  • http://localhost:8080/trigger/discardoldest?taskName=任务4

  • 代码说明

  • 线程池配置

    • 使用 ThreadPoolTaskExecutor 创建线程池。

    • 配置了 4 个不同的线程池,每个线程池使用不同的拒绝策略。

    • 每个线程池的核心线程数为 5,最大线程数为 10,队列容量为 100。

  • 拒绝策略

    • AbortPolicy:直接抛出 RejectedExecutionException

    • CallerRunsPolicy:由提交任务的线程直接执行任务。

    • DiscardPolicy:静默丢弃新任务,不抛异常。

    • DiscardOldestPolicy:丢弃队列中最旧的任务,然后重试提交新任务。

    • 任务执行

      • TaskService 类中的每个方法都使用 @Async 注解,并指定使用的线程池。

      • executeTask 方法模拟任务执行,包含一个 2 秒的睡眠时间。

      • 通过这个示例,你可以观察不同拒绝策略在任务被拒绝时的行为。例如,当线程池满时,AbortPolicy 会抛出异常,CallerRunsPolicy 会让提交任务的线程执行任务,DiscardPolicy 会静默丢弃任务,而 DiscardOldestPolicy 会丢弃最旧的任务并尝试提交新任务

    • 6、最佳配置

    • · 合理设置线程池参数
      CPU 密集型任务:核心线程数 ≈ CPU 核心数
      I/O 密集型任务:核心线程数 ≈ CPU 核心数 * 2,并增大队列容量。
      · 避免队列无限堆积
      设置合理的 queueCapacity,防止内存溢出(OOM)。
      · 统一异常处理
      通过 AsyncUncaughtExceptionHandler 捕获异步任务中的异常:

    • @Configurationpublic class AsyncConfig implements AsyncConfigurer {@Overridepublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();// ... 配置参数return executor;}@Overridepublic AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {return (ex, method, params) -> {// 处理异常};}}
      

      应用退出时,调用 shutdown() 并等待剩余任务执行完毕

    • executor.shutdown();try {if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {executor.shutdownNow();}} catch (InterruptedException e) {executor.shutdownNow();}
      

      总结:

    • ThreadPoolTaskExecutor 是 Spring 生态中管理线程任务的利器,通过灵活的配置和与 Spring 的无缝集成,能够高效处理异步任务、高并发请求和定时调度。合理设置参数、选择拒绝策略,并结合监控手段,可显著提升系统性能和稳定性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/85104.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/85104.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Elasticsearch/OpenSearch MCP Quickstart

项目概述 elasticsearch-mcp-server 是一个基于 Model Context Protocol (MCP) 的服务器实现&#xff0c;提供了与 Elasticsearch 和 OpenSearch 交互的能力。该服务器允许用户搜索文档、分析索引以及管理集群&#xff0c;通过一系列工具函数实现这些功能。 项目结构 项目主…

《Elasticsearch 分布式搜索在聊天记录检索中的深度优化》

Elasticsearch 分布式搜索在聊天记录检索中的深度优化 引言 在现代聊天应用中&#xff0c;聊天记录检索面临着数据量大、查询复杂、实时性要求高的多重挑战。以某社交平台为例&#xff0c;其聊天记录每天新增数千万条&#xff0c;总数据量达百亿级&#xff0c;用户需要在海量…

CSS实现元素撑满剩余空间的5种方法

CSS实现元素撑满剩余空间的5种方法 &#x1f3a8; 在日常开发中&#xff0c;我们经常需要让某个元素占据容器的剩余空间。这是一个常见的布局需求&#xff0c;比如侧边栏主内容区、头部内容区底部等布局。本文将介绍5种不同的方法来实现这个需求&#xff0c;并分析各种方法的优…

[AI]从零开始的YOLO数据集增强教程

一、前言 不知道大家在训练YOLO时有没有遇到过这样的情况&#xff0c;明明数据集已经准备了很多了&#xff0c;但是YOLO还是不认识某个物品&#xff0c;或者置信度低。那么有没有办法让我们不制作新数据集的情况下让代码帮我们生成新的数据集来训练模型呢&#xff1f;当然有&am…

软件工程的相关名词解释

目录 1. 软件生命周期2.开源软件3.软件工程4.模块化原则5.信息隐藏原则6.双向追踪7.原型8.软件需求9.需求工程10.边界类11.软件实现&#xff08;的任务&#xff09;12.软件缺陷13.回归测试14.软件β版15.软件部署16.纠正性维护17.改善性维护18.适应性维护19.软件逻辑老化 1. 软…

2025.06.17【BUG】|多样品VCF文件合并技巧及注意事项(以bcftools为例)

文章目录 [toc]一、合并VCF的常用命令1.1 合并多个bgzip压缩的VCF文件1.2 使用文件列表合并 二、合并前的准备与注意事项2.1 文件格式要求2.2 样本名唯一性2.3 检查文件模式匹配 三、常见报错与解决方法3.1 报错&#xff1a;Error: Duplicate sample names (sample1), use --fo…

包含30个APP客户端UI界面的psd适用于旅游酒店项目

包含30个APP客户端UI界面的psd适用于旅游酒店项目 此资源包含30个完全可编辑的psd界面组成。内容包括欢迎页、登录、注册、首页、搜索、侧边菜单、用户中心、个人介绍、用户空间、产品详细信息、酒店预定、天气情况等各种常用界面&#xff0c;您可以将其用于旅游酒店类的APP应用…

ArrayList源码分析

目录 ArrayList简介 ArrayList和vector的区别&#xff08;了解即可&#xff09; ArrayList添加null值 ArrayList和LinkedList区别 ArrayList核心源码解读 ArrayList扩容机制分析 一步一分析ArrayList扩容机制 hugeCapacity()方法 System.arraycopy() Arrays.copyOf()方法 …

NX二次开发C#---通过Face找Edges,再通过Edges找Curve

文章介绍了一个名为AskFaceEdge的静态方法&#xff0c;用于处理3D建模中的边缘曲线生成。该方法通过NX Open API调用&#xff0c;主要功能是获取指定面的边缘并生成相应的曲线。方法接收两个参数&#xff1a;faceTag&#xff08;面标签&#xff09;和curveLoop&#xff08;曲线…

设计模式笔记_创建型_工厂模式

1. 工厂模式简介 工厂模式是一种创建型设计模式&#xff0c;主要用于创建对象实例。 它通过定义一个接口或抽象类来创建对象&#xff0c;而不是直接实例化具体类&#xff0c;从而将对象的创建过程与使用过程分离。 工厂模式通常分为两种类型&#xff1a; 简单工厂模式&#x…

2025.6.16总结

工作&#xff1a;今天闭环了个遗留问题。在做专项评估时写得太简单&#xff0c;这让测试经理质疑你的测试质量。如果换位思考&#xff0c;你是测试经理&#xff0c;你该怎么去把握风险和保证产品的质量&#xff0c;就知道写得太简单&#xff0c;没有可信度。 找开发看了下后台…

记录:安装VMware、Ubuntu、ROS2

安装了VMware&#xff0c;就能够在Windows系统装安装Ubuntu&#xff0c;使用Linux系统。安装了Ubuntu&#xff0c;就能在里面安装ROS2&#xff0c;之后写代码控制机器人儿。 安装VMware 我安装的是16 pro【具体是vmware16.2.4】&#xff0c;下载网站&#xff1a;VMware Works…

将后端数据转换为docx文件

使用docx npm install docx 按照注释处理数据并转换为对应的bolb数据流 <template><Button type"primary" click"handleDocxCreate">{{buttonTitle || "报告生成"}}</Button> </template><script> import {Doc…

数据结构排序算法合集

快排 private static void quickSort(int[] ret) { quick(ret,0,ret.length-1); } private static void quick(int[] ret, int left, int right) { if(left>right) 记一下这里是大于等于 return; int pivot partition(ret,left,right); quick(ret…

【算法笔记】红黑树插入操作

红黑树插入与调整详解 一、红黑树的五大性质 红黑树是一种自平衡的二叉搜索树&#xff08;BST&#xff09;&#xff0c;其核心特性如下&#xff1a; 颜色属性&#xff1a;每个节点非红即黑根属性&#xff1a;根节点必须为黑色叶子属性&#xff1a;所有的 NIL 叶子节点都是黑…

认知计算革命:从算法创新到产业落地的AI专业核心应用全景

​​一、自动化机器学习&#xff08;AutoML&#xff09;​​ ​​技术机理与产业实践深度剖析​​ ​​神经网络架构搜索&#xff08;NAS&#xff09;​​ 强化学习方案&#xff1a;Google Brain的NASNet采用策略梯度优化卷积单元进化算法方案&#xff1a;DeepMind的AmeobaNe…

篇章十 论坛系统——业务开发——板块和帖子

目录 1.板块 1.1 思路 1.2 实现逻辑 1.3 参数要求 1.4 实现步骤 1.Mapper.xml 2.Mapper.java 3.Service接口 4.Service实现 5.单元测试 6.Controller 7.测试API 8.前后端交互 2.帖子 1.1思路​编辑 1.2 参数要求 ​编辑 1.3 实现步骤 1.Mapper.xml 2.Mapper…

React Native 上线前的准备与企业实战经验总结

上线前的准备与企业实战经验总结 关键要点 热更新简化部署&#xff1a;CodePush 和 Expo OTA 允许快速推送 JavaScript 和资源更新&#xff0c;绕过应用商店审核&#xff0c;适合修复 Bug 或小规模功能迭代。监控与分析提升质量&#xff1a;Sentry 提供实时错误跟踪&#xff…

【AI时代速通QT】第一节:C++ Qt 简介与环境安装

目录 前言 一、为什么是 Qt&#xff1f;—— C 开发者的必备技能 二、Qt 的核心魅力&#xff1a;不止于跨平台 2.1 优雅之一&#xff1a;代码隔离&#xff0c;清晰明了 2.2 优雅之二&#xff1a;信号与槽&#xff08;Signal & Slot&#xff09;机制 2.3 优雅之三&…

pandas学习笔记

前言 总结才是知识&#xff0c;作者习惯不好&#xff0c;不会总结&#xff0c;导致函数一旦不使用就会忘记怎么使用&#xff0c;特此写了本文&#xff0c;用于给自己一个复习的资料. 提示&#xff1a;如果你是小白&#xff0c;每个代码请自己敲打。 一 pandas的介绍 Pandas is…