多線程 - 線程池的4種拒絕策略


1.拒絕時機


線程池會在以下兩種情況下會拒絕新提交的任務

當我們調用 shutdown 等方法關閉線程池的時候,如果此時繼續向線程池提交任務,就會被拒絕
當任務隊列(workQueue)已滿,而且線程達到最大線程數(maximumPoolSize),如果再增加任務,也會被拒絕

2.拒絕策略

2.1 核心接口

java.util.concurrent.RejectedExecutionHandler

public interface RejectedExecutionHandler {
    void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}

 

2.2 內建實現

2.2.1 CallerRunsPolicy

  • java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy

當有新任務提交后,如果線程池沒被關閉且沒有能力執行,則把這個任務交於提交任務的線程執行,也就是誰提交任務,誰就負責執行任務。這樣做主要有兩點好處。

第一點新提交的任務不會被丟棄,這樣也就不會造成業務損失。
第二點好處是,由於誰提交任務誰就要負責執行任務,這樣提交任務的線程就得負責執行任務,而執行任務又是比較耗時的,在這段期間,提交任務的線程被占用,也就不會再提交新的任務,減緩了任務提交的速度,相當於是一個負反饋。在此期間,線程池中的線程也可以充分利用這段時間來執行掉一部分任務,騰出一定的空間,相當於是給了線程池一定的緩沖期。

2.2.2 AbortPolicy

  • java.util.concurrent.ThreadPoolExecutor.AbortPolicy

拒絕策略在拒絕任務時,會直接拋出一個類型為 RejectedExecutionException 的 RuntimeException,讓你感知到任務被拒絕了,於是你便可以根據業務邏輯選擇重試或者放棄提交等策略。

2.2.3 DiscardPolicy

  • java.util.concurrent.ThreadPoolExecutor.DiscardPolicy

當新任務被提交后直接被丟棄掉,也不會給你任何的通知,相對而言存在一定的風險,因為我們提交的時候根本不知道這個任務會被丟棄,可能造成數據丟失。

2.2.4 DiscardOldestPolicy

  • java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy

如果線程池沒被關閉且沒有能力執行,則會丟棄任務隊列中的頭結點,通常是存活時間最長的任務,這種策略與第二種不同之處在於它丟棄的不是最新提交的,而是隊列中存活時間最長的,這樣就可以騰出空間給新提交的任務,但同理它也存在一定的數據丟失風險。

參考文獻


版權聲明:本文為CSDN博主「不懂的浪漫」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/xiewenfeng520/article/details/106954167




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM