線程池-四種拒絕策略總結


一、線程池的拒絕策略
線程池中,有三個重要的參數,決定影響了拒絕策略:corePoolSize - 核心線程數,也即最小的線程數。workQueue - 阻塞隊列 。 maximumPoolSize - 最大線程數
當提交任務數大於 corePoolSize 的時候,會優先將任務放到 workQueue 阻塞隊列中。當阻塞隊列飽和后,會擴充線程池中線程數,直到達到 maximumPoolSize 最大線程數配置。此時,再多余的任務,則會觸發線程池的拒絕策略了。總結起來,也就是一句話,當提交的任務數大於(workQueue.size() + maximumPoolSize ),就會觸發線程池的拒絕策略。
二、拒絕策略定義
拒絕策略提供頂級接口 RejectedExecutionHandler ,其中方法 rejectedExecution 即定制具體的拒絕策略的執行邏輯。
jdk默認提供了四種拒絕策略:

  • CallerRunsPolicy - 當觸發拒絕策略,只要線程池沒有關閉的話,則使用調用線程直接運行任務。一般並發比較小,性能要求不高,不允許失敗。但是,由於調用者自己運行任務,如果任務提交速度過快,可能導致程序阻塞,性能效率上必然的損失較大
  • AbortPolicy - 丟棄任務,並拋出拒絕執行 RejectedExecutionException 異常信息。線程池默認的拒絕策略。必須處理好拋出的異常,否則會打斷當前的執行流程,影響后續的任務執行。
  • DiscardPolicy - 直接丟棄,其他啥都沒有
  • DiscardOldestPolicy - 當觸發拒絕策略,只要線程池沒有關閉的話,丟棄阻塞隊列 workQueue 中最老的一個任務,並將新任務加入

三、測試代碼
1、AbortPolicy

    public static void main(String[] args) throws Exception{
        int corePoolSize = 5;
        int maximumPoolSize = 10;
        long keepAliveTime = 5;
        BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(10);
        RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardOldestPolicy();
        ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue, handler);
        for(int i=0; i<100; i++) {
            try {
                executor.execute(new Thread(() -> log.info(Thread.currentThread().getName() + " is running")));
            } catch (Exception e) {
                log.error(e.getMessage(),e);
            }
        }
        executor.shutdown();
    }

executor.execute()提交任務,由於會拋出 RuntimeException,如果沒有try.catch處理異常信息的話,會中斷調用者的處理流程,后續任務得不到執行(跑不完100個)。可自行測試下,很容易在控制台console中能查看到。
2、CallerRunsPolicy
主體代碼同上,更換拒絕策略:

RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();

運行后,在控制台console中能夠看到的是,會有一部分的數據打印,顯示的是 “main is running”,也即體現調用線程處理。
3、DiscardPolicy
更換拒絕策略

RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();

直接丟棄任務,實際運行中,打印出的信息不會有100條。
4、DiscardOldestPolicy
同樣的,更換拒絕策略:

RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardOldestPolicy();

實際運行,打印出的信息也會少於100條。
五、總結
四種拒絕策略是相互獨立無關的,選擇何種策略去執行,還得結合具體的業務場景。實際工作中,一般直接使用 ExecutorService 的時候,都是使用的默認的 defaultHandler ,也即 AbortPolicy 策略。

參考博客:
https://www.cnblogs.com/eric-fang/p/11584142.html
https://blog.csdn.net/suifeng629/article/details/98884972


免責聲明!

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



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