Java執行緒池底層原始碼分享和相關面試題(持續更新)

頭髮少少少。發表於2021-06-14

執行緒池各個引數講解

public ThreadPoolExecutor(int corePoolSize, //執行緒池核心工作執行緒數量,比如newFixedThreadPool中可以自定義的執行緒數量就是這個引數
                              int maximumPoolSize, //執行緒池所有工作執行緒的數量,比如newFixedThreadPool中的最大工作執行緒就是核心執行緒數,newCachedThreadPool中的最大工作執行緒數是Integer.MAX_VALUE
                              long keepAliveTime, //非核心執行緒存活的時間,當核心執行緒不夠用的時候,建立出來的輔助工作執行緒在完成任務空閒多久後會被回收
                              TimeUnit unit, //上面一個引數的單位,分。秒等
                              BlockingQueue<Runnable> workQueue,//底層使用的阻塞佇列資料結構,比如newFixedThreadPool底層使用LinkedBlockingQueue。工作佇列,儲存已提交但是未執行的任務
                              ThreadFactory threadFactory, //建立工作執行緒的工廠,保持預設即可
                              RejectedExecutionHandler handler) { //拒絕策略,即在所有工作執行緒數達到上限,底層阻塞佇列也滿了的時候採取的策略
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

常用執行緒池

1.newSingleThreadExecutor 單個執行緒的執行緒池,即執行緒池中每次只有一個執行緒工作,單執行緒序列執行任務

2.newFixedThreadExecutor(n) 固定數量的執行緒池,沒提交一個任務就是一個執行緒,直到達到執行緒池的最大數量,然後後面進入等待佇列直到前面的任務完成才繼續執行

3.newCacheThreadExecutor(推薦使用) 可快取執行緒池,當執行緒池大小超過了處理任務所需的執行緒,那麼就會回收部分空閒(一般是60秒無執行)的執行緒,當有任務來時,又智慧的新增新執行緒來執行。

4.newScheduleThreadExecutor 大小無限制的執行緒池,支援定時和週期性的執行執行緒

執行緒池底層執行原理

 

日常使用中使用哪種執行緒池

上面四種都不使用,我們需要通過ThreadPoolExcutor自定義執行緒池,阿里巴巴java開發手冊明確指出,不允許使用Excutors工具類進行執行緒池的建立,因為某些開發人員不瞭解底層執行規則,避免資源耗盡的危險

1:FixedThreadPool 和 SingleThreadPool: 允許的請求佇列(底層實現是LinkedBlockingQueue)長度為Integer.MAX_VALUE,可能會堆積大量的請求,從而導致OOM

2:CachedThreadPool 和 ScheduledThreadPool 允許的建立執行緒數量為Integer.MAX_VALUE,可能會建立大量的執行緒,從而導致OOM

執行緒池4種拒絕策略

new ThreadPoolExecutor.AbortPolicy(); //遇到執行緒池達到最大執行緒數,且佇列已經滿了,直接拋異常 ----預設

new ThreadPoolExecutor.DiscardOldestPolicy() //遇到執行緒池達到最大執行緒數且佇列已經滿了,則丟棄佇列中最前面的任務,

new ThreadPoolExecutor.DiscardPolicy() //遇到執行緒池達到最大執行緒數且佇列已經滿了,丟棄當前任務,不給它加入佇列中

new ThreadPoolExecutor.CallerRunsPolicy();//會將任務返回給提交者進行執行,比如讓main執行緒直接執行run方法

執行緒池優點

1.避免大量執行緒的建立銷燬帶來的效能開銷

2.避免大量執行緒之間因為相互搶佔系統資源導致的阻塞狀態

3.能夠對執行緒進行簡單的管理並提供定時執行,間隔執行等功能

在IO密集型和CPU密集型下執行緒池最大執行緒數選擇

在CPU密集型下,選用cpu核心數+1作為最大執行緒池工作執行緒數量,減少cpu切換任務帶來的開銷

在IO密集型下,儘可能多的加大工作執行緒數量,一般為cpu核心數*2

執行緒池提交任務時excute和submit有什麼區別

1.兩者接收引數不一致,excute接收Runnable介面,submit接收Callable介面

2.submit有返回值,execute沒有返回值

3.submit支援返回Future

執行緒池狀態

private static final int RUNNING    = -1 << COUNT_BITS;
private static final int SHUTDOWN   =  0 << COUNT_BITS;
private static final int STOP       =  1 << COUNT_BITS;
private static final int TIDYING    =  2 << COUNT_BITS;
private static final int TERMINATED =  3 << COUNT_BITS;

RUNNING:執行緒池的初始狀態,可以新增待執行的任務

SHUTDOWN:執行緒池處於待關閉狀態,不接受新任務,但會處理完已接收的任務

STOP:執行緒池立即關閉,不接收新的任務,放棄快取佇列中的任務並且中斷正在處理的任務

TIDYING:執行緒池自主整理狀態,呼叫 terminated() 方法進行執行緒池整理

TERMINATED:執行緒池終止狀態

相關文章