Java線程池的四種拒絕策略詳解
dk1.5版本新增了 JUC 并發(fā)包,其中一個包含線程池。
四種拒絕策略:
| 拒絕策略類型 | 說明 | |
|---|---|---|
| 1 | ThreadPoolExecutor.AbortPolicy | 默認(rèn)拒絕策略,拒絕任務(wù)并拋出任務(wù) |
| 2 | ThreadPoolExecutor.CallerRunsPolicy | 使用調(diào)用線程直接運(yùn)行任務(wù) |
| 3 | ThreadPoolExecutor.DiscardPolicy | 直接拒絕任務(wù),不拋出錯誤 |
| 4 | ThreadPoolExecutor.DiscardOldestPolicy | 觸發(fā)拒絕策略,只要還有任務(wù)新增,一直會丟棄阻塞隊列的最老的任務(wù),并將新的任務(wù)加入 |
預(yù)先配置
配置線程池。
- 核心線程和最大線程都盡量設(shè)置的小一點(diǎn),分別設(shè)置成 1 和 2
- 阻塞隊列設(shè)置固定長度的有界隊列,長度為 1
- 線程工廠設(shè)置默認(rèn)線程工廠
// 核心線程數(shù) int corePoolSize = 1; // 最大線程數(shù) int maximumPoolSize = 2; // 線程存活時間 long keepAliveTime = 10; // 線程存活時間單位 TimeUnit unit = TimeUnit.SECONDS; // 有界隊列 遵循 FIFO 原則 BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(1); // 線程工廠 ThreadFactory threadFactory = Executors.defaultThreadFactory();
創(chuàng)建線程任務(wù)
創(chuàng)建線程任務(wù),一個線程任務(wù)執(zhí)行一秒:
class TaskThread implements Runnable{
private int i;
public TaskThread(int i) {
this.i = i;
}
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(2);
System.out.println("執(zhí)行任務(wù):" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}拒絕策略一:AbortPolicy
默認(rèn)拒絕策略,拒絕任務(wù)并拋出任務(wù)
// 拒絕策略 默認(rèn)拒絕策略,拒絕任務(wù)并拋出異常:
RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(corePoolSize,
maximumPoolSize,
keepAliveTime,
unit,
workQueue,
threadFactory,
handler);
for (int i = 1; i <= 5; i++) {
try {
threadPool.execute(new TaskThread(i));
} catch (Exception e) {
System.out.println("【任務(wù)" + i + "】報錯:" + e.getMessage());
}
}輸出
【任務(wù)】4報錯:Task com.test.controller.ThreadPoolController$TaskThread@5c0369c4 rejected from java.util.concurrent.ThreadPoolExecutor@50675690[Running, pool size = 2, active threads = 2, queued tasks = 1, completed tasks = 0]
【任務(wù)】5報錯:Task com.test.controller.ThreadPoolController$TaskThread@31b7dea0 rejected from java.util.concurrent.ThreadPoolExecutor@50675690[Running, pool size = 2, active threads = 2, queued tasks = 1, completed tasks = 0]
執(zhí)行任務(wù):1
執(zhí)行任務(wù):3
執(zhí)行任務(wù):2
最大線程數(shù) + 阻塞隊列 = 3,執(zhí)行到4,5的時候就拋出錯誤。這里需要用 try catch 捕獲異常。任務(wù)1、2、3正常執(zhí)行。
如果提交的任務(wù)都要執(zhí)行,可以將拋出的錯誤任務(wù)存入在redis中,然后定時從redis中獲取任務(wù),再提交執(zhí)行。
拒絕策略二:CallerRunsPolicy
調(diào)用線程運(yùn)行多余的任務(wù)。
更換拒絕策略,將上面的 AbortPolicy 換成 CallerRunsPolicy。
RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();
執(zhí)行任務(wù),輸出:
執(zhí)行任務(wù):1
執(zhí)行任務(wù):4
執(zhí)行任務(wù):3
執(zhí)行任務(wù):2
執(zhí)行任務(wù):5
最大線程數(shù) + 阻塞隊列 = 3,多余的任務(wù)還是繼續(xù)被執(zhí)行。
拒絕策略三:DiscardPolicy
拒絕任務(wù),不會拋出錯誤。
更換策略,將CallerRunsPolicy 換成DiscardPolicy:
RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();
執(zhí)行任務(wù),輸出:
執(zhí)行任務(wù):1
執(zhí)行任務(wù):3
執(zhí)行任務(wù):2
MAKEFILE 復(fù)制 全屏
多余的線程任務(wù)提交被拒絕,而只執(zhí)行最大線程數(shù) + 阻塞隊列 數(shù)量的任務(wù),并且不會拋出錯誤。
拒絕策略四:DiscardOldestPolicy
只要還有任務(wù)新增,一直會丟棄阻塞隊列的最老的任務(wù),并將新的任務(wù)加入到阻塞隊列中。
更換策略,將DiscardPolicy 換成DiscardOldestPolicy:
RejectedExecutionHandler handler3 = new ThreadPoolExecutor.DiscardOldestPolicy();
執(zhí)行任務(wù),輸出:
執(zhí)行任務(wù):3
執(zhí)行任務(wù):1
執(zhí)行任務(wù):5
任務(wù)的執(zhí)行順序是 核心線程數(shù) —> 阻塞隊列 —> 最大線程數(shù),其中任務(wù)1,任務(wù)3提交成功。
- 任務(wù)2因為在阻塞隊列中,
- 后面的任務(wù)4把任務(wù)2擠掉,
- 任務(wù)5又把任務(wù)4擠掉,所以最后執(zhí)行的是任務(wù)5。
總結(jié)
本文介紹了線程四種拒絕策略,當(dāng)工作任務(wù)大于最大線程 + 阻塞隊列會執(zhí)行阻塞隊列。
- AbortPolicy 默認(rèn)策略,拒絕任務(wù),并拋出異常
- CallerRunsPolicy 調(diào)用線程執(zhí)行對于的任務(wù)
- DiscardPolicy 拒絕任務(wù),不會拋出異常
- DiscardOldestPolicy 有多余的任務(wù),把阻塞隊列最老的任務(wù)丟棄,放入新的任務(wù),直到?jīng)]有新的任務(wù)。
到此這篇關(guān)于Java線程池的四種拒絕策略的文章就介紹到這了,更多相關(guān)Java 線程池拒絕策略內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java實現(xiàn)角色及菜單權(quán)限的項目實踐
在Java中,實現(xiàn)角色及菜單權(quán)限管理涉及定義實體類、設(shè)計數(shù)據(jù)庫表、實現(xiàn)服務(wù)層和控制器層,這種管理方式有助于有效控制用戶權(quán)限,適用于企業(yè)級應(yīng)用,感興趣的可以一起來了解一下2024-09-09
Java用數(shù)組實現(xiàn)循環(huán)隊列的示例
下面小編就為大家?guī)硪黄狫ava用數(shù)組實現(xiàn)循環(huán)隊列的示例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-09-09
如何使用nexus在局域網(wǎng)內(nèi)搭建maven私服及idea的使用
這篇文章主要介紹了如何使用nexus在局域網(wǎng)內(nèi)搭建maven私服及idea的使用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-11-11
java中靜態(tài)代碼塊與構(gòu)造方法的執(zhí)行順序判斷
對靜態(tài)代碼塊以及構(gòu)造函數(shù)的執(zhí)行先后順序,一直很迷惑,直到最近看到一段代碼,發(fā)現(xiàn)終于弄懂了,所以這篇文章主要給大家介紹了關(guān)于如何判斷java中靜態(tài)代碼塊與構(gòu)造方法的執(zhí)行順序的相關(guān)資料,需要的朋友可以參考下。2017-12-12
Java實現(xiàn)學(xué)生信息管理系統(tǒng)(使用數(shù)據(jù)庫)
這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)學(xué)生信息管理系統(tǒng),使用數(shù)據(jù)庫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01
MyBatis的JdbcType與Oracle、MySql數(shù)據(jù)類型一覽表
這篇文章主要介紹了MyBatis的JdbcType與Oracle、MySql數(shù)據(jù)類型一覽表,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01
MybatisPlus如何調(diào)用count函數(shù)
這篇文章主要介紹了MybatisPlus如何調(diào)用count函數(shù)問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08
Java?Map.values()方法之如何獲取Map集合中的所有鍵值對象
這篇文章主要介紹了Java?Map.values()方法之如何獲取Map集合中的所有鍵值對象問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03

