線程池狀態
ThreadPoolExcutor使用int高3位來表示線程池狀態,低29位表示線程數量
狀態 | 高三位 | 接收新任務 | 處理阻塞隊列任務 | 說明 |
RUNNING | 111 | Y | Y | |
SHUTDOWN | 000 | N | Y | 不會接收新任務,但會處理阻塞隊列剩余任務,比較溫和,已經提交的任務都會執行。 |
STOP | 001 | N | N | 會中斷正在執行的任務,并拋棄阻塞隊列任務,比較暴力。 |
TIDYING | 010 | 任務全部執行完畢,活動線程為0即將進入終結 | ||
TERMINATED | 011 | 終結狀態 |
從數字上比較:
TERMINATED > TIDYING > STOP > SHUTDOWN > RUNNING
RUNNING 111, 最高位1表示負數。
?問題
為啥將線程池的狀態和線程數量存在一個int類型的變量中?
存儲在一個原子變量ctl中,目的是將線程池狀態與線程個數合二為一,這樣就可以用一次cas原子操作進行賦值。
構造方法
corePoolSize 核心線程數目(最多保留的線程數)
maxmumPoolSize 最大線程數目
keepAliveTime 生存時間-針對救急線程
unit 時間單位-針對救急線程
workQueue 阻塞隊列
threadFactory 線程工廠-可以為線程創建時起好名字
handler 拒絕策略
最大線程數 = 核心線程數 + 救急線程數
執行流程:先給核心線程執行任務,然后再將線程放到阻塞隊列中,最后給救急線程執行任務,最后執行拒絕策略。
最開始線程池里是沒有線程的,屬于一種懶加載,只有有任務要執行的時候,才會創建線程。
救急線程與核心線程的區別:
救急線程是有存活時間的。
核心線程執行完任務會一直保留在線程池中。
拒絕策略:
AbortPolicy 讓調用者拋出RejectedExecutionException異常,默認策略。
CallerRunsPolicy 讓調用者運行任務。
DiscardPolicy 放棄本次任務。
DiscardOldestPolicy 放棄隊列中最早的任務,本任務取而代之。
這是jdk提供的這四種拒絕策略都實現了RejectedExecutionHandler接口:?
還有第三方框架提供的實現:
1.Dubbo實現,拋出RejectedExecutionException異常之前會記錄日志,并dump線程棧信息,方便定位問題。
2.Netty實現,創建一個新線程來執行任務。
3.ActiveMQ的實現,帶超時等待60s嘗試放入隊列,類似之前自定義拒絕策略。
4.PinPoint的實現,使用了一個拒絕策略鏈,會逐一嘗試策略鏈中沒中拒絕策略。