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
英文地址,請注明出處:http://en.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;…