淺析Java如何實(shí)現(xiàn)動態(tài)線程池的任務(wù)編排
在開始聊動態(tài)線程池如何實(shí)現(xiàn)任務(wù)編排前,咱們先給大家聊聊什么是動態(tài)線程池?以及為什么需要任務(wù)編排?
1.動態(tài)線程池
定義:動態(tài)線程池是在程序運(yùn)行期間,動態(tài)調(diào)整線程池參數(shù)而無需重啟程序的技術(shù)。
特性分析
動態(tài)線程池主要有以下三個(gè)特點(diǎn):
1.可配置:支持運(yùn)行時(shí)動態(tài)調(diào)整線程池參數(shù),如核心線程數(shù)、最大線程數(shù),并且修改后無需重啟服務(wù)即可生效。
2.可監(jiān)控:動態(tài)線程池內(nèi)置了全面的運(yùn)行時(shí)監(jiān)控能力,能夠定時(shí)采集并暴露線程池的多維度指標(biāo),幫助運(yùn)維和開發(fā)人員實(shí)時(shí)掌握線程池的健康狀況。監(jiān)控指標(biāo)主要有以下幾個(gè):
- 線程維度:當(dāng)前線程數(shù)、活躍線程數(shù)、最大線程數(shù)、任務(wù)完成數(shù)、任務(wù)執(zhí)行異常數(shù)等。
- 隊(duì)列維度:隊(duì)列當(dāng)前大小、隊(duì)列剩余容量等。
- 任務(wù)維度:任務(wù)提交速率、任務(wù)執(zhí)行耗時(shí)(TP99、TP999等)、任務(wù)等待耗時(shí)、任務(wù)拒絕次數(shù)等。
3.可預(yù)警:動態(tài)線程池提供了豐富且及時(shí)的預(yù)警機(jī)制,能夠在線程池出現(xiàn)潛在風(fēng)險(xiǎn)或異常行為時(shí),第一時(shí)間通知到相關(guān)負(fù)責(zé)人。
預(yù)警維度:
- 配置變更通知:當(dāng)線程池配置項(xiàng)在配置中心被修改時(shí),會發(fā)送通知確認(rèn)變更。
- 活性報(bào)警:當(dāng)線程池的活躍度(活躍線程數(shù) / 最大線程數(shù))超過設(shè)定閾值時(shí)觸發(fā)。
- 隊(duì)列容量報(bào)警:當(dāng)任務(wù)隊(duì)列的使用率(當(dāng)前大小 / 隊(duì)列容量)超過設(shè)定閾值時(shí)觸發(fā)。
- 拒絕策略觸發(fā)報(bào)警:當(dāng)線程池因隊(duì)列滿和線程滿而觸發(fā)拒絕策略,拒絕新任務(wù)時(shí)立即報(bào)警。
- 任務(wù)執(zhí)行/等待超時(shí)報(bào)警:當(dāng)任務(wù)的執(zhí)行時(shí)間或等待時(shí)間超過設(shè)定的超時(shí)時(shí)間時(shí)觸發(fā)。
通知渠道:
- 原生支持:企業(yè)微信、釘釘、飛書、郵件等多種主流辦公通訊工具。
- 高擴(kuò)展性:提供 SPI 接口,允許用戶接入自定義的報(bào)警通知平臺。
動態(tài)線程池實(shí)現(xiàn)
目前國內(nèi)最知名的動態(tài)線程池開源實(shí)現(xiàn)技術(shù)是美團(tuán)的 DynamicTP,官方地址:dynamictp.cn/
2.任務(wù)編排
定義:任務(wù)編排(Task Orchestration)是指管理和控制多個(gè)任務(wù)的執(zhí)行流程,確保它們按照預(yù)定的順序正確執(zhí)行。
在復(fù)雜的業(yè)務(wù)場景中,任務(wù)間通常存在依賴關(guān)系,也就是某個(gè)任務(wù)會依賴另一個(gè)任務(wù)的執(zhí)行結(jié)果,在這種情況下,我們需要通過任務(wù)編排,來確保任務(wù)按照正確的順序進(jìn)行執(zhí)行。
例如,以下任務(wù)的執(zhí)行順序:

其中,任務(wù)二要等任務(wù)一執(zhí)行完才能執(zhí)行,而任務(wù)四要等任務(wù)二和任務(wù)三全部執(zhí)行完才能執(zhí)行。
3.動態(tài)線程池任務(wù)編排
動態(tài)線程池的任務(wù)編排最靈活、也最推薦的是使用:CompletableFuture + DynamicTP 實(shí)現(xiàn)動態(tài)線程池的任務(wù)編排。
具體實(shí)現(xiàn)
我們可以直接將 DynamicTP 結(jié)合 CompletableFutrue 進(jìn)行使用,從而實(shí)現(xiàn)任務(wù)編排。
CompletableFutrue 提供的方法有很多,但最常用和最實(shí)用的核心方法只有以下幾個(gè):

接下來,使用 CompletableFuture 實(shí)現(xiàn)上述 4 個(gè)任務(wù)的編排(任務(wù)二要等任務(wù)一執(zhí)行完才能執(zhí)行,而任務(wù)四要等任務(wù)二和任務(wù)三全部執(zhí)行完才能執(zhí)行):
// 動態(tài)線程池
@Autowired
@Qualifier("dtpExecutor1")
private DtpExecutor dtpExecutor;
@RequestMapping("/dtp")
public String dtp() {
// 任務(wù)一:返回 "Task 1 result"
CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> {
try {
// 模擬耗時(shí)操作
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
return "Task 1 result";
}, dtpExecutor);
// 任務(wù)二:依賴任務(wù)一,返回 "Task 2 result" + 任務(wù)一的結(jié)果
CompletableFuture<String> task2 = task1.handleAsync((result1, throwable) -> {
try {
// 模擬耗時(shí)操作
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
return "Task 2 result " + result1;
}, dtpExecutor);
// 任務(wù)三:和任務(wù)一、任務(wù)二并行執(zhí)行,返回 "Task 3 result"
CompletableFuture<String> task3 = CompletableFuture.supplyAsync(() -> {
try {
// 模擬耗時(shí)操作
Thread.sleep(800); // 任務(wù)三可能比任務(wù)二先完成
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
return "Task 3 result";
}, dtpExecutor);
// 任務(wù)四:依賴任務(wù)二和任務(wù)三,等待它們都完成后執(zhí)行,返回 "Task 4 result" + 任務(wù)二和任務(wù)三的結(jié)果
CompletableFuture<String> task4 = CompletableFuture.allOf(task2, task3)
.handleAsync((res, throwable) -> {
try {
// 這里不需要顯式等待,因?yàn)?allOf 已經(jīng)保證了它們完成
return "Task 4 result with " + task2.get() + " and " + task3.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}, dtpExecutor);
// 獲取任務(wù)四的結(jié)果并打印
String finalResult = task4.join();
System.out.println(finalResult);
}
小結(jié)
日常項(xiàng)目開發(fā)中,一定會使用到線程池,而動態(tài)線程池具備可配置、可觀測、可告警等功能是項(xiàng)目開發(fā)的首選。但在使用動態(tài)線程池時(shí)就會有任務(wù)執(zhí)行順序的問題,此時(shí)就可以借助 CompletableFuture 一起執(zhí)行來保證程序執(zhí)行的正確性。
到此這篇關(guān)于淺析Java如何實(shí)現(xiàn)動態(tài)線程池的任務(wù)編排的文章就介紹到這了,更多相關(guān)Java線程池任務(wù)編排內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
不喜歡羅里吧嗦,講的很精簡易懂。從基礎(chǔ)開始講,后續(xù)會講到JAVA高級,中間會穿插面試題和項(xiàng)目實(shí)戰(zhàn),希望能給大家?guī)韼椭?/div> 2022-03-03
菜鳥學(xué)習(xí)java設(shè)計(jì)模式之單例模式
這篇文章主要為大家詳細(xì)介紹了java設(shè)計(jì)模式之單例模式的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11
SpringBoot中日志切面實(shí)現(xiàn)小結(jié)
本文介紹了SpringBoot中日志切面實(shí)現(xiàn)小結(jié),通過定義一個(gè)自定義注解和創(chuàng)建一個(gè)日志切面類,為方法添加日志記錄功能,感興趣的可以了解一下2024-11-11
ElasticSearch啟動成功卻無法在瀏覽器訪問問題解決辦法
因工作的需要,要使用elasticsearch,安裝完了,啟動也成功了之后發(fā)現(xiàn)了問題,這篇文章主要給大家介紹了關(guān)于ElasticSearch啟動成功卻無法在瀏覽器訪問問題的解決辦法,需要的朋友可以參考下2024-10-10
SpringBoot接入deepseek深度求索示例代碼(jdk1.8)
這篇文章主要介紹了SpringBoot接入deepseek深度求索的相關(guān)資料,包括建API?key、封裝詢問Deepseek的工具方法(在配置文件中添加key值)、調(diào)用測試并確保端口一致例如8091,最后運(yùn)行結(jié)果,需要的朋友可以參考下2025-02-02
IDEA實(shí)現(xiàn) springmvc的簡單注冊登錄功能的示例代碼
這篇文章主要介紹了IDEA實(shí)現(xiàn) springmvc的簡單注冊登錄功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
Springboot初始化啟動報(bào)錯(cuò)Error?creating?bean?with?name?'da
這篇文章主要為大家介紹了Springboot初始化啟動報(bào)Error?creating?bean?with?name?'dataSource'?defined?in?class?path?resource解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
Java中import java.util.Scanner的用處詳解
文章主要介紹Java中的Scanner類及其常用方法next()和nextLine()的區(qū)別,next()方法在遇到空格、Tab鍵、回車鍵等分隔符時(shí)結(jié)束輸入,而nextLine()方法則接收所有輸入,直到遇到回車鍵2024-11-11最新評論

