在Spring中,CompletableFuture通常用於非同步程式設計,可以方便地處理非同步任務的執行和結果處理,CompletableFuture
是 Java 8 引入的一個類,用於支援非同步程式設計和併發操作。它基於 Future 和 CompletionStage 介面,提供了豐富的方法來處理非同步任務的執行和結果處理。
下面是 CompletableFuture
實現的一些關鍵原理:
-
執行緒池支援:
CompletableFuture
內部使用執行緒池來執行非同步任務,可以透過指定不同的執行緒池來控制任務的執行方式。預設情況下,CompletableFuture
使用ForkJoinPool.commonPool()
作為預設的執行緒池。 -
回撥函式:
CompletableFuture
支援鏈式呼叫,可以透過thenApply()
,thenAccept()
,thenRun()
,thenCompose()
等方法新增回撥函式,在非同步任務完成後處理任務的結果或執行下一步操作。 -
異常處理:
CompletableFuture
提供了exceptionally()
,handle()
,whenComplete()
等方法來處理非同步任務中可能丟擲的異常,確保異常能夠被捕獲並處理。 -
組合操作:
CompletableFuture
支援多個 CompletableFuture 物件之間的組合操作,如thenCombine()
,thenCompose()
,allOf()
,anyOf()
等方法,實現並行執行、序列執行、等待所有任務完成等功能。 -
CompletableFuture 工廠方法:除了
supplyAsync()
方法外,CompletableFuture
還提供了一系列工廠方法來建立 CompletableFuture 物件,如runAsync()
,completedFuture()
,failedFuture()
等,方便快速建立並管理非同步任務。
總的來說,CompletableFuture
的實現基於 Future 和 CompletionStage 介面,利用執行緒池、回撥函式、異常處理、組合操作等機制,提供了強大而靈活的非同步程式設計功能,使得開發人員能夠更加方便地處理非同步任務的執行和結果處理。
使用方法(一)鏈式
如果我們的業務方法已經寫完了,這時可以直接透過supplyAsync方法來呼叫這些已知的方法,而不需要重新開發
CompletableFuture<String> a1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "Hello World";
});
CompletableFuture<String> a2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "Hello World";
});
CompletableFuture<String> a3 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "Hello World";
});
// 這塊最後是平行計算時間為3秒
CompletableFuture.allOf(a1, a2, a3).join();
String result = a1.get() + " | " + a2.get() + " | " + a3.get();
使用方法(二)獨立方法
如果方法比較獨立,並且之前沒有開發過,那麼你可以透過非同步方法來將這些邏輯與呼叫程式碼解耦
@Service
@EnableAsync
public class ParallelTaskService {
@Async
public CompletableFuture<String> task1() {
// 模擬一個耗時操作
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return CompletableFuture.completedFuture("Task 1 completed");
}
@Async
public CompletableFuture<String> task2() {
// 模擬另一個耗時操作
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return CompletableFuture.completedFuture("Task 2 completed");
}
}
// 平行計算時,響應時間是2和3秒之中最大值,即3秒
@GetMapping("/hello-world2")
public CompletableFuture<String> helloWorld2() {
CompletableFuture<String> task1Result = parallelTaskService.task1();
CompletableFuture<String> task2Result = parallelTaskService.task2();
// 等待所有任務都完成
CompletableFuture<Void> allOf = CompletableFuture.allOf(task1Result, task2Result);
// 處理所有任務完成後的邏輯
return allOf.thenApply(voidResult -> {
String result = task1Result.join() + " | " + task2Result.join();
return result;
});
}