1. 程式人生 > >threadPoolExecutor 中的 shutdown() 、 shutdownNow() 、 awaitTermination() 的用法和區別

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

文章目錄


最近在看併發程式設計,在使用到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
  4. 然後返回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()
  4. 關閉功能 【從強到弱】 依次是:shuntdownNow() > shutdown() > awaitTermination()