JUC之線程池的實現原理以及拒絕策略

線程池實現原理

向線程池提交任務後,線程池如何來處理這個任務,之前我們瞭解了7個參數,我們通過這些參數來串聯其線程池的實現原理。

image-20220119163714794

image-20220119163758655

1、在創建了線程池後,開始等待請求

2、當調用execute()方法添加請求任務時:

  • 如果正在運行的線程小於corePoolSize(核心線程數),那麼馬上創建線程執行任務;
  • 如果正在運行的線程數量大於或等於corePoolSize,那麼將這個任務放入阻塞隊列中;
  • 如果這個時候隊列滿了且正在運行的線程數量還小於maximumPoolSize(最大線程數),那麼再創建非核心線程來執行任務
  • 如果這個時候隊列滿了且正在運行的線程數量還大於或等於maximumPoolSize(最大線程數),那麼線程池會啓動飽和拒絕策略來執行

3、當一個線程完成任務時,他會從隊列中取出下一個任務來執行

4、當一個線程無事可做並超過了一定的時間(KeepAliveTime)時,線程會回收。

拒絕策略

等待隊列已經排滿,再也塞不下新任務,同時線程池中的max線程也到達上限了,無法繼續執行新任務服務,這時候就需要據拒絕策略。

內置的拒絕策略有四種:

  1. AbortPolicy(默認的拒絕策略):直接拋出RejectedExecutionException異常
  2. CallerRunPolicy:回退任務,該策略不拋棄任務,也不拋出異常,而是將任務會退給調用者,從而降低新任務的流量
  3. DiscardOldestPolicy:拋棄隊列中等待最久的任務,然後把當前任務加人隊列中嘗試再次提交當前任務。
  4. DiscardPolicy:該策略默默地丟棄無法處理的任務,不予任何處理也不拋出異常。如果允許任務丟失,這是最好的一種策略。

根據阿里巴巴手冊,定義線程池需要使用ThreadPoolExecutor來創建:

package com.JucPool;

import java.util.concurrent.*;

public class demo1 {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2,
            	//根據自己的處理器數量+1
                Runtime.getRuntime().availableProcessors()+1,
                2L,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        try{
            for (int i = 0; i < 8; i++) {
                executor.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"\t任務執行");
                });
            }
        } finally {
            executor.shutdown();
        }
    }
}

如果項目時CPU密集型,則設置的線程池的最大線程數是:CPU數+1~2個。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章