一、線程池簡介
在Java中,使用線程來異步執行任務。Java線程的創建與銷燬需要一定的開銷,如果我們爲每個任務創建一個新的線程來執行,這些線程的創建與銷燬將消耗大量的計算資源。Java的線程在此情況下,既是工作單元,也是執行機制。爲了減少創建線程的額外開支,將工作單元與執行機制分離不失爲一個好辦法。由此,Java線程池自然的被設計出了。
合理地使用線程池帶來極大的好處:
1)降低資源消耗:通過重複利用已創建的線程降低線程創建和銷燬帶來的開銷。
2)提高響應速度:當任務到達時,任務可以不需要等待線程創建就能立刻執行。
3)提高線程的可管理性:線程是稀缺資源,如果無限制地創建,不僅會消耗資源,而且會降低系統的穩定性,使用線程池可以進行統一分配、調優和監控。
但是,要充分發揮線程池的優點,就必須掌握其使用方法和適用條件,對其實現原理也必須瞭如指掌。下面我們主要介紹線程池的主要實現類ThreadPoolExecutor。
二、線程池的狀態
ThreadPoolExecutor中一共有5種狀態。分別是:
- RUNNING:接受新的任務並且處理阻塞隊列中的任務。
- SHUTDOWN:拒絕新的任務,但是會將阻塞隊列中的任務完成。
- STOP:拒絕新的任務,拋棄阻塞隊列中的任務,中斷正在處理的任務。
- TIDYING:所有任務都已經執行完成,線程池中活動線程爲0,阻塞隊列也爲空,此時將要調用 terminated()方法。
- TERMINATED:執行完terminated()方法,線程池處於終止狀態。
三、線程池狀態轉換
- RUNNING=》SHUTDOWN
- RUNNING or SHUTDOWN =》STOP
- SHUTDOWN =》 TIDYING
- STOP=》TIDYING
- TIDYING=》TERMINATED
四、線程池參數
- corePoolSize:線程池核心線程個數
- workQueue:阻塞隊列,用於保存等待執行的任務。
- maximumPoolSize:線程池最大線程數量
- threadFactory:創建線程的工廠
- RejectedExecutionHandler:飽和策略,當隊列滿了並且活動線程數達到maximumPoolSize時採取的策略。
- keepAliveTime:存活時間,當活動線程數大於核心線程數並且處於閒置狀態,這些閒置線程能存活的最大時間。
- TimeUnit:存活時間單位。
五、線程池主要處理流程
- 判斷核心線程池裏面線程是否已滿。如果未滿,則創建新的工作線程執行任務。如果已滿,則進入下個流程。
- 判斷工作隊列是否滿了。如果未滿,則加入工作隊列。如果滿了,進入下個流程。
- 判斷線程池線程數有沒有達到最大線程數。如果滿了,採取飽和策略。如果未滿,創建線程執行任務。
六、RejectedExecutionHandler策略
- AbortPolicy:直接拋出異常。
- CallerRunsPolicy:只用調用者線程來運行。
- DiscardOldestPolicy:丟棄隊列裏最近的一個任務,並執行當前任務。
- DiscardPolicy:不處理,直接丟棄。