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

