Java線程池ThreadPoolExecutor面試總結思維導圖速記
優點
- 降低資源消耗,通過重複利用已創建的線程降低線程創建和銷毀造成的消耗。
- 提高響應速度,當任務到達時,可以不需要等待線程創建就能立即執行。
- 提高線程的可管理性
類關係
接 Executor 一個無返回值的execute方法
接 ExecutorService 返回值為Future類型的submit方法
類 AbstractExecutorService
類 ThreadPoolExecutor
創建
ThreadPoolExecutor類
包含參數
corePoolSize: 核心線程數最大值
maximumPoolSize: 最大線程數大小
keepAliveTime: 非核心線程空閑的存活時間大小
unit: 線程空閑存活時間單位
workQueue: 存放任務的阻塞隊列
threadFactory: 用於設置創建線程的工廠
handler: 線城池的飽和策略事件
參數workQueue有如下幾種隊列
- ArrayBlockingQueue; 必須帶參構造,數組,默認非公平可指定,FIFO
- LinkedBlockingQueue; 可帶參構造,大小默認int最大,FIFO
- SynchronousQueue;不存儲元素,每個插入操作必須等到另一個線程調用移除操作,否則堵塞
- PriorityBlockingQueue;優先級,數組
- DelayQueue; 基於PriorityQueue,延時阻塞隊列,只有當其指定的延遲時間到了,才能夠從隊列中獲取到該元素。
參數hander有如下幾種
- AbortPolicy 丟棄任務並拋異常,默認
- DiscardPolicy 直接丟棄任務
- DiscardOldestPolicy 丟棄隊列最前面的任務,然後重新嘗試執行任務(重複此過程)
- CallerRunsPolicy 由調用線程處理該任務
Executors類
阿里巴巴開發規範不允許使用Executors去創建,因為隊列OOM。
主要有如下幾種
- newCachedThreadPool():一個任務創建一個線程,使用SynchronousQueue,用於並發執行大量短期的小任務。
- newFixedThreadPool(nThreads):所有任務使用固定大小的線程池,使用LinkedBlockingQueue,適用執行長期的任務
- newSingleThreadExecutor():只有一個線程的線程池,使用LinkedBlockingQueue,適用於串行執行任務的場景,
執行流程
在 execute() 中實現,當提交一個線程時
- 如果正在運行的線程數 < coreSize,馬上創建線程執行該task,不排隊等待;
- 如果正在運行的線程數 >= coreSize,把該task放入隊列;
- 如果隊列已滿 && 正在運行的線程數 < maximumPoolSize,創建新的線程執行該task;
4 . 如果隊列已滿 && 正在運行的線程數 >= maximumPoolSize,線程池調用handler的reject方法拒絕本次提交。
異常捕獲
默認不捕獲異常,捕獲方法如下
- try-catch
- submit執行,Future.get接受異常
- 重寫ThreadPoolExecutor的afterExecute方法,處理傳遞的異常引用
- 為工作者線程設置UncaughtExceptionHandler,在uncaughtException方法中處理異常
線程池狀態
running
該狀態的線程池會接收新任務,並處理阻塞隊列中的任務;
- shutdown() -> shutdown
- shutdownNow() -> stop
shutdown
該狀態的線程池不會接收新任務,但會處理阻塞隊列中的任務;
- 隊列為空,並且線程池中執行的任務也為空,進入tidying狀態;
stop
該狀態的線程不會接收新任務,也不會處理阻塞隊列中的任務,而且會中斷正在運行的任務;
- 線程池中執行的任務為空,進入tidying狀態;
tidying
該狀態表明所有的任務已經運行終止,記錄的任務數量為0。
- terminated() -> terminated
terminated
該狀態表示線程池徹底終止
線程大小設置
- 如果是CPU密集型任務,就需要盡量壓榨CPU,參考值可以設為 N(cpu) + 1
- 如果是IO密集型任務,參考值可以設置為2 * N(cpu)