1. 程式人生 > 其它 >面試突擊29:說一下執行緒池7個引數的含義

面試突擊29:說一下執行緒池7個引數的含義

所謂的執行緒池的 7 大引數是指,在使用 ThreadPoolExecutor 建立執行緒池時所設定的 7 個引數,如以下原始碼所示:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
    //...
}

這 7 個引數分別是:

  1. corePoolSize:核心執行緒數。
  2. maximumPoolSize:最大執行緒數。
  3. keepAliveTime:空閒執行緒存活時間。
  4. TimeUnit:時間單位。
  5. BlockingQueue:執行緒池任務佇列。
  6. ThreadFactory:建立執行緒的工廠。
  7. RejectedExecutionHandler:拒絕策略。

引數1:corePoolSize

核心執行緒數:是指執行緒池中長期存活的執行緒數。

這就好比古代大戶人家,會長期僱傭一些“長工”來給他們幹活,這些人一般比較穩定,無論這一年的活多活少,這些人都不會被辭退,都是長期生活在大戶人家的。

引數2:maximumPoolSize

最大執行緒數:執行緒池允許建立的最大執行緒數量,當執行緒池的任務佇列滿了之後,可以建立的最大執行緒數。

這是古代大戶人家最多可以僱傭的人數,比如某個節日或大戶人家有人過壽時,因為活太多,僅靠“長工”是完不成任務,這時就會再招聘一些“短工”一起來幹活,這個最大執行緒數就是“長工”+“短工”的總人數,也就是招聘的人數不能超過 maximumPoolSize。

注意事項

最大執行緒數 maximumPoolSize 的值不能小於核心執行緒數 corePoolSize,否則在程式執行時會報 IllegalArgumentException 非法引數異常,如下圖所示:

引數3:keepAliveTime

空閒執行緒存活時間,當執行緒池中沒有任務時,會銷燬一些執行緒,銷燬的執行緒數=maximumPoolSize(最大執行緒數)-corePoolSize(核心執行緒數)。

還是以大戶人家為例,當大戶人家比較忙的時候就會僱傭一些“短工”來幹活,但等幹完活之後,不忙了,就會將這些“短工”辭退掉,而 keepAliveTime 就是用來描述沒活之後,短工可以在大戶人家待的(最長)時間。

引數4:TimeUnit

時間單位:空閒執行緒存活時間的描述單位,此引數是配合引數 3 使用的。
引數 3 是一個 long 型別的值,比如引數 3 傳遞的是 1,那麼這個 1 表示的是 1 天?還是 1 小時?還是 1 秒鐘?是由引數 4 說了算的。
TimeUnit 有以下 7 個值:

  1. TimeUnit.DAYS:天
  2. TimeUnit.HOURS:小時
  3. TimeUnit.MINUTES:分
  4. TimeUnit.SECONDS:秒
  5. TimeUnit.MILLISECONDS:毫秒
  6. TimeUnit.MICROSECONDS:微妙
  7. TimeUnit.NANOSECONDS:納秒

引數5:BlockingQueue

阻塞佇列:執行緒池存放任務的佇列,用來儲存執行緒池的所有待執行任務。
它可以設定以下幾個值:

  1. ArrayBlockingQueue:一個由陣列結構組成的有界阻塞佇列。
  2. LinkedBlockingQueue:一個由連結串列結構組成的有界阻塞佇列。
  3. SynchronousQueue:一個不儲存元素的阻塞佇列,即直接提交給執行緒不保持它們。
  4. PriorityBlockingQueue:一個支援優先順序排序的無界阻塞佇列。
  5. DelayQueue:一個使用優先順序佇列實現的無界阻塞佇列,只有在延遲期滿時才能從中提取元素。
  6. LinkedTransferQueue:一個由連結串列結構組成的無界阻塞佇列。與SynchronousQueue類似,還含有非阻塞方法。
  7. LinkedBlockingDeque:一個由連結串列結構組成的雙向阻塞佇列。

比較常用的是 LinkedBlockingQueue,執行緒池的排隊策略和 BlockingQueue 息息相關。

引數6:ThreadFactory

執行緒工廠:執行緒池建立執行緒時呼叫的工廠方法,通過此方法可以設定執行緒的優先順序、執行緒命名規則以及執行緒型別(使用者執行緒還是守護執行緒)等。
執行緒工廠的使用示例如下:

public static void main(String[] args) {
    // 建立執行緒工廠
    ThreadFactory threadFactory = new ThreadFactory() {
        @Override
        public Thread newThread(Runnable r) {
            // 建立執行緒池中的執行緒
            Thread thread = new Thread(r);
            // 設定執行緒名稱
            thread.setName("Thread-" + r.hashCode());
            // 設定執行緒優先順序(最大值:10)
            thread.setPriority(Thread.MAX_PRIORITY);
            //......
            return thread;
        }
    };
    // 建立執行緒池
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 10, 0,
                                                                   TimeUnit.SECONDS, new LinkedBlockingQueue<>(),
                                                                   threadFactory); // 使用自定義的執行緒工廠
    threadPoolExecutor.submit(new Runnable() {
        @Override
        public void run() {
            Thread thread = Thread.currentThread();
            System.out.println(String.format("執行緒:%s,執行緒優先順序:%d",
                                             thread.getName(), thread.getPriority()));
        }
    });
}

以上程式的執行結果如下:

從上述執行結果可以看出,自定義執行緒工廠起作用了,執行緒的名稱和執行緒的優先順序都是通過執行緒工廠設定的。

引數7:RejectedExecutionHandler

拒絕策略:當執行緒池的任務超出執行緒池佇列可以儲存的最大值之後,執行的策略。
預設的拒絕策略有以下 4 種:

  • AbortPolicy:拒絕並丟擲異常。
  • CallerRunsPolicy:使用當前呼叫的執行緒來執行此任務。
  • DiscardOldestPolicy:拋棄佇列頭部(最舊)的一個任務,並執行當前任務。
  • DiscardPolicy:忽略並拋棄當前任務。

執行緒池的預設策略是 AbortPolicy 拒絕並丟擲異常。

總結

本文介紹了執行緒池的 7 大引數:

  1. corePoolSize:核心執行緒數,執行緒池正常情況下保持的執行緒數,大戶人家“長工”的數量。
  2. maximumPoolSize:最大執行緒數,當執行緒池繁忙時最多可以擁有的執行緒數,大戶人家“長工”+“短工”的總數量。
  3. keepAliveTime:空閒執行緒存活時間,沒有活之後“短工”可以生存的最大時間。
  4. TimeUnit:時間單位,配合引數 3 一起使用,用於描述引數 3 的時間單位。
  5. BlockingQueue:執行緒池的任務佇列,用於儲存執行緒池待執行任務的容器。
  6. ThreadFactory:執行緒工廠,用於建立執行緒池中執行緒的工廠方法,通過它可以設定執行緒的命名規則、優先順序和執行緒型別。
  7. RejectedExecutionHandler:拒絕策略,當任務量超過執行緒池可以儲存的最大任務數時,執行的策略。

是非審之於己,譭譽聽之於人,得失安之於數。

公眾號:Java面試真題解析

面試合集:https://gitee.com/mydb/interview