springboot~CompletableFuture並行計算

在Spring中,CompletableFuture通常用於異步編程,可以方便地處理異步任務的執行和結果處理,CompletableFuture 是 Java 8 引入的一個類,用於支持異步編程和併發操作。它基於 Future 和 CompletionStage 接口,提供了豐富的方法來處理異步任務的執行和結果處理。

下面是 CompletableFuture 實現的一些關鍵原理:

  1. 線程池支持CompletableFuture 內部使用線程池來執行異步任務,可以通過指定不同的線程池來控制任務的執行方式。默認情況下,CompletableFuture 使用 ForkJoinPool.commonPool() 作爲默認的線程池。

  2. 回調函數CompletableFuture 支持鏈式調用,可以通過 thenApply(), thenAccept(), thenRun(), thenCompose() 等方法添加回調函數,在異步任務完成後處理任務的結果或執行下一步操作。

  3. 異常處理CompletableFuture 提供了 exceptionally(), handle(), whenComplete() 等方法來處理異步任務中可能拋出的異常,確保異常能夠被捕獲並處理。

  4. 組合操作CompletableFuture 支持多個 CompletableFuture 對象之間的組合操作,如 thenCombine(), thenCompose(), allOf(), anyOf() 等方法,實現並行執行、串行執行、等待所有任務完成等功能。

  5. 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;
    });
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章