說一說如何優雅的關閉線程池?
優雅地關閉線程池意味着確保所有正在執行的任務都能完成,同時不會接受新的任務,並且不會突然終止正在運行的線程。
Java 提供了幾種方法來優雅地關閉線程池,主要通過 shutdown()
和 awaitTermination()
方法來實現。
示例和講解
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
public class GracefulShutdownExample {
public static void main(String[] args) {
// 創建一個固定大小的線程池
ExecutorService executorService = Executors.newFixedThreadPool(2);
// 提交一些任務給線程池
for (int i = 0; i < 5; i++) {
executorService.submit(new Task(i));
}
// 發起關閉線程池的請求,不再接受新任務
executorService.shutdown();
try {
// 等待線程池中的所有任務完成,或者超時
if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {
// 如果在指定時間內沒有完成,強制關閉線程池
executorService.shutdownNow();
System.out.println("線程池強制關閉");
} else {
System.out.println("線程池優雅關閉");
}
} catch (InterruptedException e) {
// 捕獲InterruptedException異常,強制關閉線程池
executorService.shutdownNow();
Thread.currentThread().interrupt(); // 恢復被中斷的狀態
System.out.println("線程池在中斷時被關閉");
}
}
static class Task implements Runnable {
private final int taskId;
public Task(int taskId) {
this.taskId = taskId;
}
@Override
public void run() {
System.out.println("任務 " + taskId + " 開始執行");
try {
// 模擬任務執行時間
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢復被中斷的狀態
System.out.println("任務 " + taskId + " 被中斷");
}
System.out.println("任務 " + taskId + " 完成");
}
}
}
講解
-
1. 創建線程池:
ExecutorService executorService = Executors.newFixedThreadPool(2);
這裏創建了一個固定大小爲 2 的線程池。
-
2. 提交任務:
for (int i = 0; i < 5; i++) { executorService.submit(new Task(i)); }
提交了 5 個任務到線程池中。
-
3. 關閉線程池:
executorService.shutdown();
調用
shutdown()
方法,線程池進入關閉狀態,不再接受新任務,但會繼續執行已經提交的任務。 -
4. 等待任務完成:
if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) { executorService.shutdownNow(); System.out.println("線程池強制關閉"); } else { System.out.println("線程池優雅關閉"); }
調用
awaitTermination(long timeout, TimeUnit unit)
方法,等待線程池中的任務在指定的時間內完成。如果在規定時間內沒有完成,調用shutdownNow()
強制關閉線程池。 -
5. 處理中斷異常:
} catch (InterruptedException e) { executorService.shutdownNow(); Thread.currentThread().interrupt(); System.out.println("線程池在中斷時被關閉"); }
捕獲
InterruptedException
異常,強制關閉線程池,並恢復被中斷的狀態。 -
6. 任務類:
static class Task implements Runnable { // ... 模擬任務執行,可能會拋出 InterruptedException }
定義了一個簡單的任務類,每個任務會睡眠 2 秒鐘,模擬執行時間。
關鍵點
-
• shutdown():啓動線程池的關閉過程,不再接受新任務,但已提交的任務會繼續執行。
-
• awaitTermination(long timeout, TimeUnit unit):等待線程池在指定時間內關閉。
-
• shutdownNow():嘗試立即關閉線程池,嘗試停止所有正在執行的任務,返回未執行的任務列表。
-
• 處理中斷:確保在捕獲
InterruptedException
異常時,能夠正確地恢復中斷狀態並強制關閉線程池。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/c6PlbmTNJY3JO0BWvx0mow