掌握 ExecutorService 關閉:追蹤線程池終止
假設您想要執行一些任務。由於透過單一執行緒執行它可能需要相當長的時間才能獲得結果,因此您決定使用可靠的 ExecutorService 透過多個執行緒處理它。
這是一個範例:
public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(5); for (int i = 0; i < 5; i++) { int temp = i; executorService.submit(() -> { task(temp); }); } executorService.shutdown(); System.out.println("ExecutorService is shutdown"); } private static void task(int temp) { try { TimeUnit.SECONDS.sleep(1L); System.out.println("Task " + temp + " completed"); } catch (InterruptedException e) { throw new RuntimeException(e); } }
當然,像往常一樣,如果不使用「睡眠」作為任務執行的原型,任何執行緒範例都是不完整的。
它輸出,
ExecutorService is shutdown Task 1 completed Task 2 completed Task 0 completed Task 4 completed Task 3 completed
現在想像一下有一個無窮無盡的任務隊列,而你不知道其中的數量。也許它們是由資料庫中動態添加的條目數量決定的。
例如,一家銀行,它必須全天處理大量交易。交易結束時間為下午5點,超過該時間將不再接受任何額外任務。
但是,您確實知道任務的數量是有限的,並且將在某個時間點結束。
如何知道所有任務完成的時間點?
如果您注意到上面的程式碼片段,ExecutorService.shutdown() 會使主執行緒立即退出,但後台執行緒仍然處理已接受的任務直至完成。有什麼方法可以讓您收到完成通知嗎?
我想到了幾個解決方案:
- 使用 CountDownLatch 來計算任務 - 但由於您不知道任務的數量,所以使用它是不切實際的。
- 使用ExecutorService.awaitTermination()。然而,這裡的時間仍然是不確定的。您可以使用非常自由的 ExecutorService.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS) 或類似的東西。但這又是一個阻塞呼叫。
有更好的方法來解決這個問題嗎?
Java 確實提供了一種更好且相對未知的方法來解決這個問題。這裡的「技巧」是要知道 Executors.newFixedThreadPool 本質上是一個具有預定義值的 ThreadPoolExecutor。讓我們來看看 Executors.newFixedThreadPool 的實作。
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
我真的建議閱讀這裡的 ThreadPoolExecutor 文件。 ExecutorService 是 ThreadPoolExecutor 的便利包裝。
...強烈建議程式設計師使用更方便的Executors工廠方法Executors.newCachedThreadPool()(無界執行緒池,具有自動執行緒回收功能)、Executors.newFixedThreadPool(int)(固定大小執行緒池)和Executors.newSingleThreadExecutoringleThreadExecutoringle ( )(單後台執行緒),為最常見的使用場景預先配置設定。
將幫助我們解決問題的部分是:
鉤子方法
此類提供了受保護的可重寫 beforeExecute(Thread, Runnable) 和 afterExecute(Runnable, Throwable) 方法,這些方法在每個任務執行之前和之後都被呼叫。這些可用於操縱執行環境;例如,重新初始化 ThreadLocals、收集統計資料或新增日誌條目。此外,可以重寫方法終止()以執行執行器完全終止後需要完成的任何特殊處理。
我們可以使用終止方法來通知我們同樣的事情!但我們該如何使用它呢?
public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(5); for (int i = 0; i < 5; i++) { int temp = i; executorService.submit(() -> { task(temp); }); } executorService.shutdown(); System.out.println("ExecutorService is shutdown"); } private static void task(int temp) { try { TimeUnit.SECONDS.sleep(1L); System.out.println("Task " + temp + " completed"); } catch (InterruptedException e) { throw new RuntimeException(e); } }
如果您不喜歡匿名類別(像我一樣),您始終可以自行擴展 ThreadPoolExecutor 來建立自訂類別。
ExecutorService is shutdown Task 1 completed Task 2 completed Task 0 completed Task 4 completed Task 3 completed
這是驗證它是否按照我們的預期工作的輸出。
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
您還使用了哪些其他相對未知的片段?請在評論中告訴我!
以上是掌握 ExecutorService 關閉:追蹤線程池終止的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

公司安全軟件導致部分應用無法正常運行的排查與解決方法許多公司為了保障內部網絡安全,會部署安全軟件。 ...

將姓名轉換為數字以實現排序的解決方案在許多應用場景中,用戶可能需要在群組中進行排序,尤其是在一個用...

在使用IntelliJIDEAUltimate版本啟動Spring...

系統對接中的字段映射處理在進行系統對接時,常常會遇到一個棘手的問題:如何將A系統的接口字段有效地映�...

Java對象與數組的轉換:深入探討強制類型轉換的風險與正確方法很多Java初學者會遇到將一個對象轉換成數組的�...

在使用MyBatis-Plus或其他ORM框架進行數據庫操作時,經常需要根據實體類的屬性名構造查詢條件。如果每次都手動...

Redis緩存方案如何實現產品排行榜列表的需求?在開發過程中,我們常常需要處理排行榜的需求,例如展示一個�...

電商平台SKU和SPU表設計詳解本文將探討電商平台中SKU和SPU的數據庫設計問題,特別是如何處理用戶自定義銷售屬...
