SpringBoot如何自定義線程池配置類
更新時間:2024年04月02日 16:18:09 作者:ABin-阿斌
有時候我們在項目中做一些長鏈路的跑批任務時,基于Springboot項目的定時任務,我們可以指定一個自定義的線程配置類進行單獨提供給具體跑批任務使用,而不占用整個系統(tǒng)資源,這篇文章主要介紹了SpringBoot如何自定義線程池配置類,需要的朋友可以參考下
一、前言
- 有時候我們在項目中做一些長鏈路的跑批任務時,基于Springboot項目的定時任務,我們可以指定一個自定義的線程配置類進行單獨提供給具體跑批任務使用,而不占用整個系統(tǒng)資源。
二、案例展示
- 我們觀察一下第一種方式和優(yōu)化后的對比在哪里,關鍵點什么?
1、初始版本
@Configuration @EnableAsync public class ScheduledConfig { /** * 創(chuàng)建并配置一個線程池,用于快速執(zhí)行任務。 * * @return Executor 返回一個配置好的線程池實例,可以用于快速執(zhí)行任務。 */ @Bean("baseExecutor") public Executor fastExecutor() { // 創(chuàng)建 ThreadPoolTaskExecutor 實例 ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // 設置線程名前綴 executor.setThreadNamePrefix("xxxx-schedule-baseExecutor"); // 設置最大線程池大小 executor.setMaxPoolSize(10); // 設置核心線程池大小 executor.setCorePoolSize(8); // 設置隊列容量 executor.setQueueCapacity(5); // 設置拒絕執(zhí)行處理器,采用CallerRunsPolicy策略 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); return executor; }
2、代碼審核意見和優(yōu)化建議
3、潛在問題和風險
- 異常處理: 線程池的默認異常處理機制可能不足以處理所有任務拋出的異常。盡管設置了CallerRunsPolicy作為拒絕執(zhí)行處理器,它僅在線程池飽和時工作,并不直接處理任務執(zhí)行中的異常。建議增強異常處理邏輯,例如通過自定義的RejectedExecutionHandler實現(xiàn)或者在任務代碼中加入更細粒度的異常處理。
- 資源泄露: 當應用停止時,如果線程池沒有被正確關閉,可能會導致資源泄露。雖然Spring通常會管理Bean的生命周期,但最好確認ThreadPoolTaskExecutor的實例是否加入了適當?shù)匿N毀邏輯,例如調用executor.shutdown()。
- 線程數(shù)配置: CorePoolSize被設置為8,MaxPoolSize被設置為10,這意味著在高負載情況下,線程池只能擴展到10個線程。這樣的配置可能不足以處理所有高峰時段的請求。你需要根據(jù)實際的負載測試結果調整這些參數(shù)。
- 隊列容量: 隊列容量被固定為5。這意味著一旦隊列滿了,即使線程池還沒有達到最大大小,任務也會被拒絕執(zhí)行。根據(jù)實際的負載情況,考慮適當增加隊列容量或調整線程池的大小。
4、優(yōu)化建議
- 性能監(jiān)控: 考慮添加監(jiān)控機制來跟蹤線程池的性能指標,如活躍線程數(shù)、隊列大小和拒絕執(zhí)行的任務數(shù)等。這有助于及時發(fā)現(xiàn)和調整配置參數(shù),以保證系統(tǒng)的穩(wěn)定性。
- 可調整性: 考慮將線程池的配置參數(shù)(如corePoolSize, maxPoolSize, queueCapacity等)設置為可從外部配置(例如應用配置文件)的方式獲取。這樣可以在不修改代碼的情況下調整這些參數(shù),以適應不同的運行環(huán)境。
- 定制化: 如果有更復雜的需求,比如需要執(zhí)行周期性任務或需要更細粒度的控制任務執(zhí)行,可以考慮使用Spring提供的其他任務調度組件,如 ScheduledThreadPoolExecutor 或者集成 Quartz 等第三方庫。
5、優(yōu)化后的代碼
@Configuration @EnableAsync public class ExecutorConfig { // 名字可以根據(jù)項目業(yè)務隨意起 @Bean("baseExecutor") public Executor fastExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // 線程名前綴保持不變 executor.setThreadNamePrefix("xxxx-schedule-base"); // 調整核心線程池大小、最大線程池大小和隊列容量,以適應可能的更高負載 executor.setCorePoolSize(16); // 增加核心線程數(shù) executor.setMaxPoolSize(20); // 增加最大線程數(shù) executor.setQueueCapacity(100); // 增加隊列容量 // 使用自定義的RejectedExecutionHandler來處理任務被拒絕的情況 executor.setRejectedExecutionHandler(new CustomRejectedExecutionHandler()); // 確保在應用停止時線程池能被正確關閉 Runtime.getRuntime().addShutdownHook(new Thread(() -> { executor.shutdown(); })); return executor; } // 自定義的拒絕執(zhí)行處理器,以更好地處理任務被拒絕的情況 static class CustomRejectedExecutionHandler implements RejectedExecutionHandler { @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { // 這里可以加入更詳細的日志記錄或發(fā)送警報等邏輯 System.out.println("Task " + r.toString() + " rejected from executor " + executor.toString()); } } }
三、具體使用
@Async("baseExecutor") @Scheduled(cron = "0 0/5 * * * ?"){ // 具體業(yè)務 }
到此這篇關于SpringBoot如何自定義線程池配置類的文章就介紹到這了,更多相關SpringBoot線程池配置類內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring?Security方法級安全控制@PreAuthorize注解的靈活運用小結
本文將帶著大家講解?@PreAuthorize?注解的核心原理、SpEL?表達式機制,并通過的示例代碼演示如何在實際項目中靈活運用該注解實現(xiàn)細粒度的權限控制,感興趣的朋友一起看看吧2025-04-04Spring Cloud之遠程調用OpenFeign參數(shù)傳遞
本文介紹了Spring Cloud中使用OpenFeign進行遠程調用時,參數(shù)傳遞的不同方式,包括傳遞單個參數(shù)、多個參數(shù)、對象和JSON數(shù)據(jù),感興的朋友一起看看吧2025-03-03