首頁 Java java教程 掌握 ExecutorService 關閉:追蹤線程池終止

掌握 ExecutorService 關閉:追蹤線程池終止

Jan 05, 2025 am 01:50 AM

Mastering ExecutorService Shutdown: Tracking ThreadPool Termination

假設您想要執行一些任務。由於透過單一執行緒執行它可能需要相當長的時間才能獲得結果,因此您決定使用可靠的 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() 會使主執行緒立即退出,但後台執行緒仍然處理已接受的任務直至完成。有什麼方法可以讓您收到完成通知嗎?

我想到了幾個解決方案:

  1. 使用 CountDownLatch 來計算任務 - 但由於您不知道任務的數量,所以使用它是不切實際的。
  2. 使用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中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

熱門話題

Java教學
1658
14
CakePHP 教程
1415
52
Laravel 教程
1309
25
PHP教程
1257
29
C# 教程
1231
24
公司安全軟件導致應用無法運行?如何排查和解決? 公司安全軟件導致應用無法運行?如何排查和解決? Apr 19, 2025 pm 04:51 PM

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

如何將姓名轉換為數字以實現排序並保持群組中的一致性? 如何將姓名轉換為數字以實現排序並保持群組中的一致性? Apr 19, 2025 pm 11:30 PM

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

IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? Apr 19, 2025 pm 11:45 PM

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

如何使用MapStruct簡化系統對接中的字段映射問題? 如何使用MapStruct簡化系統對接中的字段映射問題? Apr 19, 2025 pm 06:21 PM

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

Java對像如何安全地轉換為數組? Java對像如何安全地轉換為數組? Apr 19, 2025 pm 11:33 PM

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

如何優雅地獲取實體類變量名構建數據庫查詢條件? 如何優雅地獲取實體類變量名構建數據庫查詢條件? Apr 19, 2025 pm 11:42 PM

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

如何利用Redis緩存方案高效實現產品排行榜列表的需求? 如何利用Redis緩存方案高效實現產品排行榜列表的需求? Apr 19, 2025 pm 11:36 PM

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

電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? 電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? Apr 19, 2025 pm 11:27 PM

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

See all articles