【博學谷學習記錄】超強總結,用心分享。執行緒池重難點知識
執行緒池
1.1 為什麼需要執行緒池
在實際使用中,執行緒是很佔用系統資源的,如果對執行緒管理不完善的話很容易導致系統問題。因此,在大多數併發框架中都會使用執行緒池來管理執行緒,使用執行緒池管理執行緒主要有如下好處:
1、使用執行緒池可以重複利用已有的執行緒繼續執行任務,避免執行緒在建立銷燬時造成的消耗
2、由於沒有執行緒建立和銷燬時的消耗,可以提高系統響應速度
3、通過執行緒可以對執行緒進行合理的管理,根據系統的承受能力調整可執行執行緒數量的大小等
1.2 執行緒池的分類
- newCachedThreadPool:建立一個可進行快取重複利用的執行緒池
- newFixedThreadPool:建立一個可重用固定執行緒數的執行緒池,以共享的無界佇列方式來執行這些執行緒,執行緒池中的執行緒處於一定的量,可以很好的控制執行緒的併發量
- newSingleThreadExecutor : 創 建 一 個 使 用 單 個 worker 線 程 的 Executor ,以無界佇列方式來執行該執行緒。執行緒池中最多執行一個執行緒,之後提交的執行緒將會排在佇列中以此執行
- newSingleThreadScheduledExecutor:建立一個單執行緒執行程式,它可安排在給定延遲後執行命令或者定期執行
- newScheduledThreadPool:建立一個執行緒池,它可安排在給定延遲後執行命令或者定期的執行
- newWorkStealingPool:建立一個帶並行級別的執行緒池,並行級別決定了同一時刻最多有多少個執行緒在執行,如不傳並行級別引數,將預設為當前系統的 CPU 個數
1.3 核心引數
corePoolSize:核心執行緒池的大小 maximumPoolSize:執行緒池能建立執行緒的最大個數 keepAliveTime:空閒執行緒存活時間
unit:時間單位,為 keepAliveTime 指定時間單位
workQueue:阻塞佇列,用於儲存任務的阻塞佇列
threadFactory:建立執行緒的工程類
handler:飽和策略(拒絕策略)
1.4 執行緒池的原理
執行緒池的工作過程如下:
當一個任務提交至執行緒池之後,
- 執行緒池首先判斷核心執行緒池裡的執行緒是否已經滿了。如果不是,則建立一個新的工作執行緒來執行任務。否則進入
- 判斷工作佇列是否已經滿了,倘若還沒有滿,將執行緒放入工作佇列。否則進入
- 判斷執行緒池裡的執行緒是否都在執行任務。如果不是,則建立一個新的工作執行緒來執行。如果執行緒池滿了,則交給飽和策略來處理任務。
4.5 拒絕策略
ThreadPoolExecutor.AbortPolicy(系統預設): 丟棄任務並丟擲 RejectedExecutionException 異常,讓你感知到任務被拒絕了,我們可以根據業務邏輯選擇重試或者放棄提交等策略
ThreadPoolExecutor.DiscardPolicy: 也是丟棄任務,但是不丟擲異常,相對而言存在一定的風險,因為我們提交的時候根本不知道這個任務會被丟棄,可能造成資料丟失。 ThreadPoolExecutor.DiscardOldestPolicy: 丟棄佇列最前面的任務,然後重新嘗試執行任務(重複此過程),通常是存活時間最長的任務,它也存在一定的資料丟失風險 ThreadPoolExecutor.CallerRunsPolicy:既不拋棄任務也不丟擲異常,而是將某些任務回退到呼叫者,讓呼叫者去執行它。
4.6 執行緒池的關閉
關閉執行緒池,可以通過 shutdown 和 shutdownNow 兩個方法原理:遍歷執行緒池中的所有執行緒,然後依次中斷
1、shutdownNow 首先將執行緒池的狀態設定為 STOP,然後嘗試停止所有的正在執行和未執行任務的執行緒,並返回等待執行任務的列表;
2、shutdown 只是將執行緒池的狀態設定為 SHUTDOWN 狀態,然後中斷所有沒有正在執行任務的執行緒