ThreadPoolExecutor 中的 shutdown() 、 shutdownNow() 、 awaitTermination() 的用法和區別

Java併發編程中在使用到ThreadPoolExecutor時,對它的三個關閉方法(shutdown()、shutdownNow()、awaitTermination())的異同點如下:

shutdown()

將線程池狀態置爲SHUTDOWN,並不會立即停止:

  1. 停止接收外部submit的任務
  2. 內部正在跑的任務和隊列裏等待的任務,會執行完
  3. 等到第二步完成後,才真正停止

shutdownNow()

將線程池狀態置爲STOP。企圖立即停止,事實上不一定:

  1. 跟shutdown()一樣,先停止接收外部提交的任務
  2. 忽略隊列裏等待的任務
  3. 嘗試將正在跑的任務interrupt中斷
  4. 返回未執行的任務列表

它試圖終止線程的方法是通過調用Thread.interrupt()方法來實現的,但是大家知道,這種方法的作用有限,如果線程中沒有sleep 、wait、Condition、定時鎖等應用, interrupt()方法是無法中斷當前的線程的。所以,ShutdownNow()並不代表線程池就一定立即就能退出,它也可能必須要等待所有正在執行的任務都執行完成了才能退出。
但是大多數時候是能立即退出的

awaitTermination(long timeOut, TimeUnit unit)

當前線程阻塞,直到

  1. 等所有已提交的任務(包括正在跑的和隊列中等待的)執行完
  2. 或者等超時時間到
  3. 或者線程被中斷,拋出InterruptedException
    然後返回true(shutdown請求後所有任務執行完畢)或false(已超時)

shuntdown()和awaitTermination()效果差不多,方法執行之後,都要等到提交的任務全部執行完才停。

shutdown() 和 shutdownNow()的區別

從字面意思就能理解,shutdownNow()能立即停止線程池,正在跑的和正在等待的任務都停下了。這樣做立即生效,但是風險也比較大;
shutdown()只是關閉了提交通道,用submit()是無效的;而內部該怎麼跑還是怎麼跑,跑完再停。

Between client threads and thread pool there is a queue of tasks. When your application shuts down, you must take care of two things: what is happening with queued tasks and how already running tasks are behaving (more on that later). Surprisingly many developers are not shutting down thread pool properly or consciously. There are two techniques: either let all queued tasks to execute (shutdown()) or drop them (shutdownNow()) - it totally depends on your use case.

shutdown()和awaitTermination()的區別

  1. shutdown()後,不能再提交新的任務進去;但是awaitTermination()後,可以繼續提交。
  2. awaitTermination()是阻塞的,返回結果是線程池是否已停止(true/false);shutdown()不阻塞。

總結

  1. 優雅的關閉,用shutdown()
  2. 想立馬關閉,並得到未執行任務列表,用shutdownNow()
  3. 優雅的關閉,並允許關閉聲明後新任務能提交,用awaitTermination()

ps:關閉功能 【從強到弱】 依次是:shuntdownNow() > shutdown() > awaitTermination()
awaitTermination並不是用來關閉線程池,它只是用來檢測timeout時間後線程池是否關閉。
一般在調用shutdown()方法後調用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章