ThreadPoolTaskExecutor 的使用案例

ThreadPoolTaskExecutor 的使用案例

1. 依赖说明

<!-- Spring Retry(用于任务重试) -->
<dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId><version>1.3.1</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.3.22</version>
</dependency>
<!-- SLF4J MDC(用于上下文传递) -->
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.36</version>
</dependency>

2. 完整配置代码

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.backoff.FixedBackOff;
import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.backoff.FixedBackOffPolicy;
import org.springframework.core.task.TaskDecorator;import java.util.concurrent.*;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;import org.slf4j.MDC;@Configuration
public class TaskExecutorConfig {/*** 配置线程池 Bean,名称为 "taskExecutor"* 包含上下文传递机制和重试机制*/@Bean(name = "taskExecutor")public ThreadPoolTaskExecutor taskExecutor() {// 创建线程池实例ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();/*** 核心线程数:线程池中始终保留的线程数* - 建议根据任务类型调整:*   - CPU密集型任务:设为 CPU 核心数(如 Runtime.getRuntime().availableProcessors())*   - IO密集型任务:设为 2 * CPU 核心数 或更高*/executor.setCorePoolSize(5);/*** 最大线程数:线程池中允许的最大线程数* - 当队列满时,会创建新线程,直到达到 maxPoolSize* - 超出后触发拒绝策略*/executor.setMaxPoolSize(10);/*** 空闲线程存活时间(单位秒):* - 当线程数超过 corePoolSize 时,多余的线程在空闲 keepAliveSeconds 后会被回收* - 通常设置为与任务平均执行时间相当*/executor.setKeepAliveSeconds(60);/*** 任务队列:用于缓存等待执行的任务* - ArrayBlockingQueue:有界队列,容量为 25(可根据业务需求调整)* - LinkedBlockingQueue:无界队列(不推荐,可能造成内存泄漏)* - SynchronousQueue:无容量队列,适合直接传递任务(如 newCachedThreadPool)*/BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(25);executor.setQueue(queue);/*** 拒绝策略:当队列满且线程数达到最大时,新任务如何处理* - CallerRunsPolicy:由调用线程(提交任务的线程)执行任务,避免丢弃* - AbortPolicy:抛出 RejectedExecutionException(默认)* - DiscardPolicy:直接丢弃任务* - DiscardOldestPolicy:丢弃队列中最旧的任务,尝试重新提交当前任务*/executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());/*** 线程名称前缀:便于日志追踪和线程监控* - 示例输出:TaskExecutor-1, TaskExecutor-2, ...*/executor.setThreadNamePrefix("TaskExecutor-");/*** 上下文传递机制:使用 TaskDecorator 传递 MDC 上下文(如日志追踪 ID)* - MDC(Mapped Diagnostic Context)是 SLF4J 提供的日志上下文工具* - 通过 TaskDecorator,在任务执行前后传递上下文信息*/executor.setTaskDecorator(new MdcTaskDecorator());/*** 初始化线程池* - Spring 容器会自动调用此方法,但显式调用更安全*/executor.initialize();return executor;}/*** 创建重试模板(最大重试3次,间隔1秒)* - 用于包装任务,使其具备重试能力*/public static RetryTemplate createRetryTemplate() {RetryTemplate retryTemplate = new RetryTemplate();/*** 重试策略:定义重试条件和最大重试次数* - SimpleRetryPolicy:固定次数重试* - maxAttempts:最大重试次数(包含首次尝试)*/SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();retryPolicy.setMaxAttempts(3); // 最多重试3次(含首次执行)retryTemplate.setRetryPolicy(retryPolicy);/*** 重试间隔策略:定义重试之间的等待时间* - FixedBackOffPolicy:固定间隔(如 1 秒)* - ExponentialBackOffPolicy:指数退避(间隔递增)*/FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();backOffPolicy.setBackOffPeriod(1000); // 每次重试间隔 1 秒retryTemplate.setBackOffPolicy(backOffPolicy);return retryTemplate;}/*** 重试任务包装器:将任务包装为支持重试的CallableWrapper* - 通过 RetryTemplate 执行重试逻辑*/public static class RetryCallableWrapper implements Runnable {private final Runnable targetTask;private final RetryTemplate retryTemplate;public RetryCallableWrapper(Runnable targetTask, RetryTemplate retryTemplate) {this.targetTask = targetTask;this.retryTemplate = retryTemplate;}@Overridepublic void run() {retryTemplate.execute(context -> {targetTask.run(); // 执行原始任务return null; // 返回类型无关紧要(Void)});}}/*** 上下文传递装饰器:用于传递 MDC 上下文(如日志追踪 ID)* - 通过 TaskDecorator 在任务执行前后传递上下文* - 确保异步任务中能访问到主线程的上下文*/public static class MdcTaskDecorator implements TaskDecorator {@Overridepublic Runnable decorate(Runnable runnable) {// 获取当前线程的 MDC 上下文(如 traceId)Map<String, String> contextMap = MDC.getCopyOfContextMap();return () -> {try {// 恢复上下文(如 traceId)MDC.setContextMap(contextMap);// 执行任务runnable.run();} finally {// 清理上下文(可选)MDC.clear();}};}}/*** 使用示例:提交任务到线程池* - 演示上下文传递和重试机制*/public void useTaskExecutor() {ThreadPoolTaskExecutor executor = taskExecutor();// 示例1:提交带重试的任务Runnable retryableTask = new RetryCallableWrapper(() -> {System.out.println(Thread.currentThread().getName() + " 执行任务");throw new RuntimeException("模拟任务失败"); // 模拟失败}, createRetryTemplate());executor.execute(retryableTask); // 自动重试3次// 示例2:提交任务并传递上下文(如 MDC 日志追踪 ID)MDC.put("traceId", "123456"); // 设置日志追踪 IDexecutor.execute(() -> {System.out.println("当前 traceId: " + MDC.get("traceId")); // 输出 123456System.out.println(Thread.currentThread().getName() + " 执行任务");});// 关闭线程池(Spring 容器会自动关闭)// executor.shutdown();}
}

3. 配置项详解

3.1 线程池核心配置
配置项说明推荐值/示例
corePoolSize核心线程数CPU密集型:Runtime.getRuntime().availableProcessors();IO密集型:2 * CPU核心数
maxPoolSize最大线程数根据业务负载调整(如 2 * corePoolSize
keepAliveSeconds空闲线程存活时间与任务平均执行时间匹配(如 60 秒)
queue任务队列ArrayBlockingQueue(25)(有界队列)或 LinkedBlockingQueue(无界队列)
rejectedExecutionHandler拒绝策略CallerRunsPolicy(调用线程执行)、AbortPolicy(抛异常)、DiscardPolicy(丢弃任务)
threadNamePrefix线程名称前缀便于日志追踪(如 "TaskExecutor-"
3.2 上下文传递机制
  • MDC(Mapped Diagnostic Context):SLF4J 提供的日志上下文工具,用于记录日志追踪 ID。
  • TaskDecorator:Spring 提供的装饰器接口,用于在任务执行前后传递上下文。
  • 实现方式
    1. 在主线程中设置 MDC 上下文(如 MDC.put("traceId", "123456"))。
    2. 通过 TaskDecorator 将上下文传递给异步任务。
    3. 任务执行时恢复上下文,确保日志可追踪。
3.3 重试机制
  • RetryTemplate:Spring Retry 提供的重试模板,封装了重试逻辑。
  • SimpleRetryPolicy:定义最大重试次数(如 3 次)。
  • FixedBackOffPolicy:定义重试间隔(如 1 秒)。
  • 使用方式
    1. 将任务包装为 RetryCallableWrapper
    2. 通过 RetryTemplate 执行任务,自动处理重试逻辑。

4. 使用场景建议

  1. 日志追踪:通过 MDC 传递 traceId,确保异步任务日志与主线程关联。
  2. 任务重试:适用于网络请求、数据库操作等需要自动重试的场景。
  3. 资源控制:通过队列和线程数限制,防止系统过载。

5. 注意事项

  1. 重试逻辑与异常处理
    • 默认对所有异常进行重试,可通过 SimpleRetryPolicy 自定义异常类型。
    • 重试后仍失败的任务需通过日志或监控告警处理。
  2. 上下文传递的开销
    • 如果上下文较大(如包含复杂对象),需评估性能影响。
    • 使用 InheritableThreadLocal 替代 MDC 可以更灵活地传递上下文。
  3. 线程池生命周期
    • 确保在应用关闭时正确关闭线程池(调用 executor.shutdown())。
    • Spring 容器会自动关闭线程池,但手动创建时需显式调用。
  4. 队列容量与拒绝策略
    • 有界队列需合理设置容量,防止任务堆积。
    • 拒绝策略应根据业务需求选择(如 CallerRunsPolicy 适合轻量任务)。

6. 扩展功能(可选)

  1. 动态调整线程池参数:通过 ThreadPoolTaskExecutor 提供的方法(如 setCorePoolSize())动态修改配置。
  2. 监控与调优:通过 ThreadPoolTaskExecutor 的统计方法(如 getPoolSize()getQueueSize())监控线程池状态。
  3. 自定义重试策略:结合 Spring Retry 实现更复杂的重试逻辑(如指数退避、重试条件判断)。

7. 代码结构图

TaskExecutorConfig
├── taskExecutor()        // 配置线程池
│   ├── corePoolSize      // 核心线程数
│   ├── maxPoolSize       // 最大线程数
│   ├── keepAliveSeconds  // 空闲线程存活时间
│   ├── queue             // 任务队列
│   ├── rejectedHandler   // 拒绝策略
│   └── setTaskDecorator  // 上下文传递机制
├── createRetryTemplate() // 创建重试模板
├── RetryCallableWrapper // 重试任务包装器
└── useTaskExecutor()     // 使用示例├── execute()         // 提交普通任务└── submitListenable()// 提交带返回值任务

8. 总结

  • 上下文传递:确保异步任务中能访问到主线程的上下文(如日志追踪 ID)。
  • 任务重试:对失败任务自动重试,提升系统鲁棒性。
  • 灵活的线程池管理:根据业务需求调整线程池参数,避免资源浪费或过载。

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

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

相关文章

0.3mg硝酸甘油舌下片:冠心病预防中的“消防员”

冠状动脉疾病&#xff08;CAD&#xff09;如同一颗定时炸弹&#xff0c;即使在成功进行血运重建或药物治疗后&#xff0c;心绞痛急性发作的风险依然如影随形。在冠心病管理的漫长战役中&#xff0c;二级预防的核心目标不仅仅是延缓疾病进展&#xff0c;更是预防致命性心脏事件复…

【Spring源码学习系列】基础架构和环境搭建

一直以来都把精力花在中间件的研究和系统设计上&#xff0c;忽略了离我最近的spring&#xff0c;最近开始学习spring的源码了&#xff0c;为了学习到成体系的spring知识和提高学习效率&#xff0c;想要找了一本书看&#xff0c;最终选的是郝佳的《Spring源码深度解析&#xff0…

C++十大排序详解(包括变种优化)

排序**基础排序算法**1. **冒泡排序&#xff08;Bubble Sort&#xff09;**冒泡排序优化**1. 提前终止优化&#xff08;标志位优化&#xff09;****原理**&#xff1a;**实现示例**&#xff08;以C为例&#xff09;&#xff1a;**优点**&#xff1a;**2. 双向冒泡排序&#xff…

React 性能优化实战:用useTransition解决卡顿问题

文章目录1. 概述2. 基本原理与语法3. 应用场景3.1 数据密集型界面的更新优化3.2 动态内容切换的平滑过渡3.3 搜索与过滤结果的实时展示4. 与其他相关Hook的对比5. 结合Suspense使用6. 注意事项1. 概述 useTransition Hook 。它允许开发者将一些非紧急的 UI 更新标记为 “过渡更…

基于Rust红岩题材游戏、汽车控制系统、机器人运动学游戏实例

根据红岩题材设计的关键游戏实例 以下是根据红岩题材设计的关键游戏实例,结合Rust语言特性(如安全并发、ECS架构等)的框架性方案。所有设计均需符合Rust语法规范,实际开发需配合游戏引擎(如Bevy、Amethyst)。 核心系统模块 // ECS架构示例(Bevy引擎) use bevy::prel…

【ZYNQ Linux开发】BRAM的几种驱动方式

1 Vivado配置 ​ BRAM 的使用方法为使用 AXI BRAM 控制器来控制 BRAM 生成器&#xff0c;Block Design 连接如下&#xff1a; 我这里配置的是真双端口 RAM&#xff0c;通过 PL 的逻辑对 BRAM 生成器的端口 B 进行写操作&#xff0c;在 PS 端对端口 A 进行读。 BRAM 控制…

Flink ClickHouse 连接器数据写入源码深度解析

一、引言 在大数据处理的实际应用场景中&#xff0c;数据的高效存储与处理至关重要。Flink 作为一款强大的流式计算框架&#xff0c;能够对海量数据进行实时处理&#xff1b;而 ClickHouse 作为高性能的列式数据库&#xff0c;擅长处理大规模数据分析任务。Flink ClickHouse 连…

OpenCV 人脸分析------面部关键点检测类cv::face::FacemarkLBF

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 使用 Local Binary Features (LBF) 算法进行面部关键点检测&#xff08;facial landmark detection&#xff09;。该算法通过级联回归树预测人脸的…

Netstat高级分析工具:Windows与Linux双系统兼容的精准筛查利器

Netstat高级分析工具&#xff1a;Windows与Linux双系统兼容的精准筛查利器在网络安全运维中&#xff0c;快速识别可疑连接是防御入侵的关键一步。本文将介绍一款我本人开发的原创高效的双系统兼容Netstat信息分析工具&#xff0c;大幅提升恶意连接筛查效率。一、Netstat分析在安…

Bright Data MCP+Trae :快速构建电商导购助手垂直智能体

声明&#xff1a;本测试报告系作者基于个人兴趣及使用场景开展的非专业测评&#xff0c;测试过程中所涉及的方法、数据及结论均为个人观点&#xff0c;不代表任何官方立场或行业标准。 文章目录 一、引言1.1 当前AI智能体的趋势1.2 构建智能体面临的最大挑战&#xff1a;数据来…

plantuml用法总结

时序图 参考 https://blog.csdn.net/vitaviva/article/details/120735745用PlantUML简化复杂时序图的秘诀 startuml skin rose actor User as user participant "Component A" as A participant "Component B" as Buser -> A: Request data activate …

基于自研心电芯片国产化手持单导/6导/12导心电解决方案

苏州唯理作为国内心电芯片国产化厂商&#xff0c;面向家用场景&#xff0c;推出了国产化的手持单导/6导/12导心电仪技术解决方案&#xff0c;可以让家用心电图仪成本可控&#xff0c;信号链路质量更佳稳定。该方案已在多家客户中实现批量出货。唯理科技同样提供了医疗级的心电图…

Sass详解:功能特性、常用方法与最佳实践

Sass详解&#xff1a;功能特性、常用方法与最佳实践 Sass&#xff08;Syntactically Awesome Style Sheets&#xff09;作为CSS预处理器领域的先驱&#xff0c;自2006年由Hampton Catlin创建以来&#xff0c;已成为现代前端开发中不可或缺的工具。它通过引入变量、嵌套、混合宏…

vulnhub靶机渗透:PWNLAB: INIT

一、信息收集1、主机发现2、端口扫描PORT STATE SERVICE VERSION 80/tcp open http Apache httpd 2.4.10 ((Debian))111/tcp open rpcbind 2-4 (RPC #100000)3306/tcp open mysql MySQL 5.5.47-0deb8u151649/tcp open status 1 (RPC #100024)3、目录扫描&…

LiveKit 本地部署全流程指南(含 HTTPS/WSS)

1. 环境准备 操作系统&#xff1a;Windows 10/11 或 Linux/Mac需有本地公网/内网 IP&#xff08;如 192.168.x.x&#xff09;推荐浏览器&#xff1a;Chrome/Edge/Firefox/Safari端口未被占用&#xff0c;防火墙允许相关端口 2. 目录结构建议 livekit/livekit-server.execonf…

NumPy-统计函数详解

NumPy-统计函数详解一、基础统计函数&#xff1a;均值、方差、标准差1. 全局统计&#xff1a;忽略维度的整体计算2. 按轴统计&#xff1a;指定维度方向的计算二、位置统计&#xff1a;中位数、分位数、百分位数1. 中位数计算2. 分位数与百分位数三、离散程度&#xff1a;极差、…

音频被动降噪技术

音频被动降噪技术 音频被动降噪技术是一种通过物理结构和材料设计来减少或隔离外部噪声的降噪方式,其核心原理是通过物理屏障或吸声材料来阻断或吸收声波,从而降低环境噪声对听觉体验的影响。以下将从技术原理、应用场景、优缺点及与其他降噪技术的对比等方面进行详细分析。…

中国蚁剑使用方法

找到mysql配置文件 secure-file-priv工作目录 D:\tool\huli\gui_webshell\AntSword\AntSword\antSword-master重点是tool目录后面 前面大家可能都不一样 添加数据一句话木马 3C3F706870206576616C28245F504F53545B22636D64225D293B3F3E 翻译过来 <?php eval($_POST["c…

8.1 prefix Tunning与Prompt Tunning模型微调方法

1 prefix Tunning 链接&#xff1a;https://blog.csdn.net/m0_66890670/article/details/142942034 这里有基础的细节介绍。我下面直接总结。 连接2 &#xff1a;https://zhuanlan.zhihu.com/p/1899112824342577371&#xff0c;简单明了 prefix Tunning改变了什么呢&#xff…

FlashAttention 深入浅出

一 标准Attention的计算 1.1 标准Attention机制详解 标准Attention&#xff08;注意力&#xff09;机制是深度学习&#xff0c;尤其是在自然语言处理领域中一项革命性的技术&#xff0c;它允许模型在处理序列数据时&#xff0c;动态地将焦点放在输入序列的不同部分&#xff0c;…