ExecutorService 關閉 and 如何判斷執行緒池中任務執行完畢
ExecutorService 關閉
1、shutdown
2、shutdownNow
3、awaitTermination
當你使用ExecutorService
的時候,你應該記得關閉它,這樣這些被管理的執行緒才會停止執行。
舉例:如果你的應用通過main()方法啟動,並且你的 應用中存在一個 啟用的 ExecutorService,那麼即使你的main thread
(main執行緒)已經退出了,這個應用依然會在後臺執行。 原因: ExecutorService
中的活躍執行緒,防止了jvm關閉ExecutorService
。
結論:jvm是可能無法關閉ExecutorService
的,如果某些情況下,你不希望ExecutorService
ExecutorService
中的shutdown
方法。手動呼叫shutdown並不會立即關閉ExecutorService,而是等待ExecutorService中所有的任務完成,並且提交之後,才會關閉的。
這個方法會平滑地關閉ExecutorService,當我們呼叫這個方法時,ExecutorService停止接受任何新的任務且等待已經提交的任務執行完成(已經提交的任務會分兩類:一類是已經在執行的,另一類是還沒有開始執行的),當所有已經提交的任務執行完畢後將會關閉ExecutorService。
awaitTermination判斷執行的狀態,如果執行時間過長就呼叫shutdownNow 方法立即中止執行。
所以終止執行緒池分為兩個部分,一部分是shutdown 一部分是shutdownNowpublic static void shutdownAndAwaitTermination(int awaitTime, ExecutorService pool) { pool.shutdown(); //禁用提交的新任務 try { if (!pool.awaitTermination(awaitTime, TimeUnit.SECONDS)) { pool.shutdownNow(); } } catch (InterruptedException e) { pool.shutdownNow(); //(重新)取消當前執行緒是否中斷 Thread.currentThread().interrupt(); //保持中斷狀態 } }
參考:
深入理解在Android中執行緒池的使用 (shutdown那部分 有出入,作者給予了反饋感謝,牽扯的方面很多,循循漸進,點贊)
-------------------------------------------------------------------------------------
如何判斷執行緒池中任務執行完畢
這裡用到的是給使用者提供反饋,判斷多個非同步操作執行完畢的結果。
CountDownLatch是一個同步工具類,它允許一個或多個執行緒一直等待,直到其他執行緒執行完後再執行。例如,應用程式的主執行緒希望在負責啟動框架服務的執行緒已經啟動所有框架服務之後執行。
CountDownLatch是通過一個計數器來實現的,計數器的初始化值為執行緒的數量。每當一個執行緒完成了自己的任務後,計數器的值就相應得減1。當計數器到達0時,表示所有的執行緒都已完成任務,然後在閉鎖上等待的執行緒就可以恢復執行任務。
public class Test1 {
public static ExecutorService executorService = Executors.newCachedThreadPool();
private static CountDownLatch cdl = new CountDownLatch(10);
private static final Random random = new Random();
public void test() {
for (int i = 0; i < 10; i++) executorService.execute(new ThreadTest());
}
public static void main(String[] args) {
new Test1().test();
//插入資料完成後 執行修改操作
try {
cdl.await();
} catch (InterruptedException e) {
}
System.out.println("它們已經插完啦..............................");
executorService.shutdown();
}
class ThreadTest implements Runnable {
public void run() {
//執行插入資料操作 每次插入一條
// 模擬耗時
int time = random.nextInt(10000);
try {
Thread.sleep(time);
} catch (InterruptedException e) {
}
System.out.println(Thread.currentThread().getName() + "執行完了,耗時:" + time / 1000 + "秒");
cdl.countDown();
}
}
}
參考: