1. 程式人生 > >執行緒池ThreadPoolExecutor分析: 執行緒池是什麼時候建立執行緒的,佇列中的任務是什麼時候取出來的?

執行緒池ThreadPoolExecutor分析: 執行緒池是什麼時候建立執行緒的,佇列中的任務是什麼時候取出來的?

 

帶著幾個問題進入原始碼分析:

執行緒池是什麼時候建立執行緒的?

任務runnable task是先放到core到maxThread之間的執行緒,還是先放到佇列?

佇列中的任務是什麼時候取出來的?

什麼時候會觸發reject策略?

core到maxThread之間的執行緒什麼時候會die?

task丟擲異常,執行緒池中這個work thread還能執行其他任務嗎?

 

至少在new ThreadPoolExecutor()時,Thread物件並沒有初始化. 這裡僅僅指定了幾個初始引數

一段基礎程式碼,進入分析

public static void main(String[] args) {

        ExecutorService executorService = new ThreadPoolExecutor(2, 5, 0, TimeUnit.DAYS,
                new ArrayBlockingQueue<>(1), new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r);
//                thread.setDaemon(true);
                return thread;
            }
        });
        // 物件建立後,執行緒實際還沒開始建立

        // 執行execute時,檢查當前池中執行緒數大小是否小於core number, 如果是,則建立新執行緒
        executorService.execute(() -> {
            System.out.println("
[email protected]
" + Thread.currentThread().getName()); sleepTime(); System.out.println(1); }); //檢查當前池中執行緒數大小是否小於core number, 如果是,則建立新執行緒 executorService.execute(() -> { System.out.println("[email protected]" + Thread.currentThread().getName()); sleepTime(); System.out.println(2); }); // 檢查當前池中執行緒數大小是否小於core number, 如果不是,則償試放入佇列 // 這個任務是加到佇列去的, 注意佇列大小隻有1, // TODO 佇列中的任務是什麼時候取出來的? executorService.execute(() -> { System.out.println("
[email protected]
" + Thread.currentThread().getName()); sleepTime(); System.out.println(3); }); // 檢查當前池中執行緒數大小是否小於core number, 如果不是,則償試放入佇列,放入佇列也失敗,則增加新的worker執行緒 // 這個任務是加到core以外的新執行緒去的 executorService.execute(() -> { System.out.println("
[email protected]
" + Thread.currentThread().getName()); sleepTime(); System.out.println(4); }); }

  

第3行,建立一個核心池2, 最大池5, 佇列為1的執行緒池

執行第一個execute時,進入除錯jdk原始碼

 

程式碼塊1

第一個if, 判斷如果當前執行緒數小於corePoolSize, 則建立新的核心worker物件(Worker中指向Thread物件,保持引用,保證不會被GC回收)

 

我們的示例程式碼中,第1和第2個執行緒都是這樣創建出執行緒的