Java面試必問之執行緒池的建立使用、執行緒池的核心引數、執行緒池的底層工作原理

小王寫部落格發表於2022-02-10

一、前言

大家在面試過程中,必不可少的問題是執行緒池,小編也是在面試中被問啥傻了,JUC就瞭解的不多。加上做系統時,很少遇到,自己也是一知半解,最近看了尚矽谷陽哥的課,恍然大悟,特寫此文章記錄一下!如果還不瞭解執行緒池的小夥伴,一定要認真看完,你會有收穫的哈!!

二、執行緒池建立使用

答:使用Executors看一下原始碼是有好多個,經常用的也就三個,今天就展示靠上的五種。

//建立一個定長執行緒池,超出的執行緒會在佇列中等待
ExecutorService executorService = Executors.newFixedThreadPool(5);
//建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,
ExecutorService executorService1 = Executors.newSingleThreadExecutor();
//建立一個可快取執行緒池,可以自動擴容,擴容大小為int最大值,因為太大可以直接理解為無限大
ExecutorService executorService2 = Executors.newCachedThreadPool();
//建立一個定長執行緒池,該執行緒池可以安排命令在給定延遲後執行,或定期執行。
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
//1.8新增-建立一個帶並行級別的執行緒池,並行級別決定了同一時刻最多有多少個執行緒在執行,不傳引數預設為CPU個數
// Runtime.getRuntime().availableProcessors()檢視本機CPU個數
ExecutorService executorService3 = Executors.newWorkStealingPool();

三、執行緒池的核心引數

//建立執行緒池,底層程式碼
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          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.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}

1. corePoolSize:執行緒池中的核心執行緒數,核心執行緒會一直存在,即使沒有任務執行。
2. maximumPoolSize:執行緒池能夠容納同時執行的最大執行緒數,此值必須大於等於1
3. keepAliveTime:當執行緒數大於核心數時,這是多餘空閒執行緒在終止前等待新任務的最長時間。(意思就是本來核心執行緒三個,已佔滿,擴充套件到最大執行緒數到5,解決完後沒有執行緒任務了,這時設定一個時間,過了這個時間被擴充套件的2個非核心執行緒會被回收)
4. unit:keepAliveTime的時間單位。
5. workQueue:任務佇列,被提交但尚未被執行的任務,相當於去飯店吃飯,餐桌滿了,要在外邊排隊(阻塞佇列)
6. threadFactory:表示生成執行緒池中工作執行緒的執行緒工廠,用於建立執行緒一般用預設的即可。
7. handler:拒絕策略,表示當佇列滿了並且工作執行緒大於等於執行緒池的最大執行緒數。

四、執行緒池的底層工作原理

- 主要處理流程圖(來源百度)
在這裡插入圖片描述
- 底層工作原理圖(來源尚矽谷陽哥)
在這裡插入圖片描述
- 流程梳理

1. 在建立了執行緒池後,等待提交過來的任務請求。
2. 當呼叫execute()方法新增一個請求任務時,執行緒池會做如下判斷:
2.1 如果正在執行的執行緒數量小於corePoolSize,那麼馬上建立執行緒執行這個任務;
2.2 如果正在執行的執行緒數量大於或等於corePoolSize,那麼將這個任務放入佇列;
2.3 如果這時候佇列滿了且正在執行的執行緒數量還小於maximumPoolSize,那麼還是要建立非核心執行緒立刻執行這個任務;
2.4 如果佇列滿了且正在執行的執行緒數量大於或等於maximumPoolSize,那麼執行緒池會啟動飽和拒絕策略來執行。
3.當一個執行緒完成任務時,它會從佇列中取下一個任務來執行。
4.當一個執行緒無事可做超過一定的時間(keepAliveTime)時,執行緒池會判斷:
如果當前執行的執行緒數大於corePoolSize,那麼這個執行緒就被停掉;所以執行緒池的所有任務完成後它最終會收縮到corePoolSize 的大小。

五、總結

這樣就理解很透徹了,反擊尚矽谷陽哥的課程。打廣告時間到了,歡迎訪問小王部落格站,如果你也有自己的網站留言一起做個友聯!

小王部落格站

相關文章