我們知道線程是有多種執行狀態的,同樣管理線程的線程池也有多種狀態。JVM會在所有線程(非后臺daemon線程)全部終止后才退出,為了節省資源和有效釋放資源關閉一個線程池就顯得很重要。有時候無法正確的關閉線程池,將會阻止JVM的結束。
線程池Executor是異步的執行任務,因此任何時刻不能夠直接獲取提交的任務的狀態。這些任務有可能已經完成,也有可能正在執行或者還在排隊等待執行。因此關閉線程池可能出現一下幾種情況:
- 平緩關閉:已經啟動的任務全部執行完畢,同時不再接受新的任務
- 立即關閉:取消所有正在執行和未執行的任務
另外關閉線程池后對于任務的狀態應該有相應的反饋信息。
圖1 描述了線程池的4種狀態。
- 線程池在構造前(new操作)是初始狀態,一旦構造完成線程池就進入了執行狀態RUNNING。嚴格意義上講線程池構造完成后并沒有線程被立即啟動,只有進行“預啟動”或者接收到任務的時候才會啟動線程。這個會后面線程池的原理會詳細分析。但是線程池是出于運行狀態,隨時準備接受任務來執行。
- 線程池運行中可以通過shutdown()和shutdownNow()來改變運行狀態。shutdown()是一個平緩的關閉過程,線程池停止接受新的任務,同時等待已經提交的任務執行完畢,包括那些進入隊列還沒有開始的任務,這時候線程池處于SHUTDOWN狀態;shutdownNow()是一個立即關閉過程,線程池停止接受新的任務,同時線程池取消所有執行的任務和已經進入隊列但是還沒有執行的任務,這時候線程池處于STOP狀態。
- 一旦shutdown()或者shutdownNow()執行完畢,線程池就進入TERMINATED狀態,此時線程池就結束了。
- isTerminating()描述的是SHUTDOWN和STOP兩種狀態。
- isShutdown()描述的是非RUNNING狀態,也就是SHUTDOWN/STOP/TERMINATED三種狀態。

圖1
線程池的API如下:

圖2
其中shutdownNow()會返回那些已經進入了隊列但是還沒有執行的任務列表。awaitTermination描述的是等待線程池關閉的時間,如果等待時間線程池還沒有關閉將會拋出一個超時異常。
對于關閉線程池期間發生的任務提交情況就會觸發一個拒絕執行的操作。這是java.util.concurrent.RejectedExecutionHandler描述的任務操作。下一個小結中將描述這些任務被拒絕后的操作。
總結下這個小節:
-
線程池有運行、關閉、停止、結束四種狀態,結束后就會釋放所有資源
-
平緩關閉線程池使用shutdown()
-
立即關閉線程池使用shutdownNow(),同時得到未執行的任務列表
-
檢測線程池是否正處于關閉中,使用isShutdown()
-
檢測線程池是否已經關閉使用isTerminated()
-
定時或者永久等待線程池關閉結束使用awaitTermination()操作
©2009-2014 IMXYLZ
|求賢若渴