1. 線程池是何時建立線程的?java
2. 任務runnable task是先放到core到maxThread之間的線程,仍是先放到隊列?ide
3. 隊列中的任務是何時取出來的?源碼分析
4. 何時會觸發reject策略?spa
5. core到maxThread之間的線程何時會die?線程
6. task拋出異常,線程池中這個work thread還能運行其餘任務嗎?3d
先寫一段基礎代碼,進入分析調試
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("任務1@" + Thread.currentThread().getName());
sleepTime();
System.out.println(1);
});
//檢查當前池中線程數大小是否小於core number, 若是是,則建立新線程
executorService.execute(() -> {
System.out.println("任務2@" + Thread.currentThread().getName());
sleepTime();
System.out.println(2);
});
// 檢查當前池中線程數大小是否小於core number, 若是不是,則償試放入隊列
// 這個任務是加到隊列去的, 注意隊列大小隻有1,
// TODO 隊列中的任務是何時取出來的? 任務1或者2結束後所佔用的線程 會運行隊列中的任務,這個任務是在最後才運行,比4運行的還晚
executorService.execute(() -> {
System.out.println("任務3@" + Thread.currentThread().getName());
sleepTime();
System.out.println(3);
});
// 檢查當前池中線程數大小是否小於core number, 若是不是,則償試放入隊列,放入隊列也失敗,則增長新的worker線程
// 這個任務是加到core之外的新線程去的
executorService.execute(() -> {
System.out.println("任務4@" + Thread.currentThread().getName());
sleepTime();
System.out.println(4);
});
}
注意第3行,建立一個核心池2, 最大池5, 隊列爲1的線程池對象
至少在new ThreadPoolExecutor()時,Thread對象並無初始化. 這裏僅僅指定了幾個初始參數blog
執行第一個execute時,進入調試jdk源碼隊列
代碼塊1
第一個if, 判斷若是當前線程數小於corePoolSize, 則建立新的核心worker對象(Worker中指向Thread對象,保持引用,保證不會被GC回收)
咱們的示例代碼中,第1和第2個任務都是這樣建立出線程的
第二個if, 判斷若是當前線程數大於corePoolSize, 並償試放入隊列 workQueue.offer(command) , 放入成功後等待線程池調度【見後面的getTask()】
示例代碼中,第3個任務是這樣等待調度的,最後才執行
第三個if, 償試放入隊列 workQueue.offer(command) 失敗, 增長一個非core的線程
示例代碼中,第4個任務是這樣開始的
而後再看addWorker()的過程
new Worker構造和線程啓動
線程啓動後,又作了哪些工做:
沒拋異常時,此線程會一直在while(task !=null || (task = getTask())!=null)中跑
那麼有異常時,再看一下processWorkerExit
能夠 看出,有異常時 舊的worker會被刪除(GC回收),再建立新的Worker, 即有異常時 舊worker不可能再執行新的任務
Q. 線程池是何時建立線程的?
A.任務提交的時候
Q.任務runnable task是先放到core到maxThread之間的線程,仍是先放到隊列?
A.先放隊列!!!
Q. 隊列中的任務是何時取出來的?
A. worker中 runWorker() 一個任務完成後,會取下一個任務
Q. 何時會觸發reject策略?
A.隊列滿而且maxthread也滿了, 還有新任務,默認策略是reject
Q. core到maxThread之間的線程何時會die?
A. 沒有任務時,或者拋異常時。
core線程也會die的,core到maxThread之間的線程有可能會晉升到core線程區間,
core max只是個計數,線程並非建立後就固定在一個區間了
Q. task拋出異常,線程池中這個work thread還能運行其餘任務嗎?
A. 不能。 可是會建立新的線程, 新線程能夠運行其餘task。
對於 schedulerThreadPoolExecutor? 雖然有新線程,可是舊的循環任務不會再繼續執行了, 開發實踐推薦任務中捕獲全部Exception