Java CompletableFuture

Java CompletableFuture

一、简介

CompletableFuture是 Java 8 引入的一个用于异步编程的工具类,它允许你以声明式的方式编写异步代码,并且可以方便地组合和处理多个异步操作的结果。

二、创建 CompletableFuture

  1. 使用supplyAsync方法:

    • supplyAsync接受一个Supplier<T>函数式接口作为参数,该接口的get方法会在异步执行时被调用,并返回一个结果。
    • 示例:
      import java.util.concurrent.CompletableFuture;
      import java.util.concurrent.ExecutionException;
      
      public class CompletableFutureExample {
          public static void main(String[] args) throws ExecutionException, InterruptedException {
              CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
                  try {
                      // 模拟耗时操作
                      Thread.sleep(2000);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
                  return "Hello, CompletableFuture!";
              });
      
              // 获取异步操作的结果
              String result = future.get();
              System.out.println(result);
          }
      }
      
  2. 使用runAsync方法:

    • runAsync接受一个Runnable接口作为参数,用于执行一个没有返回值的异步操作。
    • 示例:
      CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
          try {
              Thread.sleep(2000);
              System.out.println("Asynchronous task completed.");
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
      });
      
      future.get();
      

三、处理结果

  1. thenApply方法:

    • thenApply接受一个Function<T, R>函数式接口作为参数,该接口的apply方法会在异步操作完成后被调用,将上一个异步操作的结果作为输入,并返回一个新的结果。
    • 示例:
      CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
          return "Hello";
      });
      
      CompletableFuture<String> newFuture = future.thenApply(result -> {
          return result + ", World!";
      });
      
      System.out.println(newFuture.get());
      
  2. thenAccept方法:

    • thenAccept接受一个Consumer<T>函数式接口作为参数,该接口的accept方法会在异步操作完成后被调用,将上一个异步操作的结果作为输入,但没有返回值。
    • 示例:
      CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
          return "Hello";
      });
      
      future.thenAccept(result -> {
          System.out.println(result + ", World!");
      });
      
      future.get();
      
  3. thenRun方法:

    • thenRun接受一个Runnable接口作为参数,该接口的run方法会在异步操作完成后被调用,不接受上一个异步操作的结果作为输入。
    • 示例:
      CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
          return "Hello";
      });
      
      future.thenRun(() -> {
          System.out.println("Task completed.");
      });
      
      future.get();
      

四、异常处理

  1. exceptionally方法:

    • exceptionally接受一个Function<Throwable, T>函数式接口作为参数,该接口的apply方法会在异步操作出现异常时被调用,并返回一个默认值或进行异常处理后的结果。
    • 示例:
      CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
          throw new RuntimeException("Something went wrong.");
      });
      
      CompletableFuture<String> newFuture = future.exceptionally(ex -> {
          return "Default value";
      });
      
      System.out.println(newFuture.get());
      
  2. handle方法:

    • handle接受一个BiFunction<T, Throwable, R>函数式接口作为参数,该接口的apply方法会在异步操作完成或出现异常时被调用,接受上一个异步操作的结果(如果成功)或异常作为输入,并返回一个结果。
    • 示例:
      CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
          if (Math.random() < 0.5) {
              return "Success";
          } else {
              throw new RuntimeException("Failure");
          }
      });
      
      CompletableFuture<String> newFuture = future.handle((result, ex) -> {
          if (ex!= null) {
              return "Error occurred: " + ex.getMessage();
          } else {
              return result + " with handle.";
          }
      });
      
      System.out.println(newFuture.get());
      

五、组合多个 CompletableFuture

  1. thenCompose方法:

    • 用于将两个异步操作串联起来,当第一个异步操作完成后,将其结果作为参数传递给第二个异步操作的函数,并返回一个新的CompletableFuture。
    • 示例:
      CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
          return "Hello";
      });
      
      CompletableFuture<String> future2 = future1.thenCompose(result1 -> CompletableFuture.supplyAsync(() -> {
          return result1 + ", World!";
      }));
      
      System.out.println(future2.get());
      
  2. thenCombine方法:

    • 用于组合两个独立的异步操作,当两个异步操作都完成后,将它们的结果作为参数传递给一个函数,并返回一个新的CompletableFuture。
    • 示例:
      CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
          return "Hello";
      });
      
      CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
          return "World!";
      });
      
      CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (result1, result2) -> {
          return result1 + ", " + result2;
      });
      
      System.out.println(combinedFuture.get());
      
  3. allOf和anyOf方法:

    • allOf接受多个CompletableFuture作为参数,返回一个CompletableFuture<Void>,当所有的CompletableFuture都完成时,这个返回的CompletableFuture才完成。
    • anyOf接受多个CompletableFuture作为参数,返回一个CompletableFuture<Object>,当其中任何一个CompletableFuture完成时,这个返回的CompletableFuture就完成,并返回第一个完成的CompletableFuture的结果。
    • 示例:
      CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
          try {
              Thread.sleep(2000);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
          return "Result 1";
      });
      
      CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
          try {
              Thread.sleep(1000);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
          return "Result 2";
      });
      
      CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2);
      allFutures.get();
      System.out.println("All futures completed.");
      
      CompletableFuture<Object> anyFuture = CompletableFuture.anyOf(future1, future2);
      System.out.println("First completed future result: " + anyFuture.get());
      

六、应用场景

  1. 并发网络请求:

    • 可以同时发起多个网络请求,并在所有请求完成后进行处理。
    • 示例:
      import java.util.concurrent.CompletableFuture;
      import java.net.URL;
      import java.io.BufferedReader;
      import java.io.InputStreamReader;
      import java.net.HttpURLConnection;
      
      public class NetworkRequestsExample {
          public static CompletableFuture<String> fetchDataFromURL(String urlStr) {
              return CompletableFuture.supplyAsync(() -> {
                  try {
                      URL url = new URL(urlStr);
                      HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                      connection.setRequestMethod("GET");
      
                      BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                      StringBuilder response = new StringBuilder();
                      String line;
                      while ((line = reader.readLine())!= null) {
                          response.append(line);
                      }
      
                      reader.close();
                      connection.disconnect();
      
                      return response.toString();
                  } catch (Exception e) {
                      throw new RuntimeException(e);
                  }
              });
          }
      
          public static void main(String[] args) throws Exception {
              String url1 = "https://example.com/api/resource1";
              String url2 = "https://example.com/api/resource2";
      
              CompletableFuture<String> future1 = fetchDataFromURL(url1);
              CompletableFuture<String> future2 = fetchDataFromURL(url2);
      
              CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2);
              allFutures.get();
      
              System.out.println(future1.get());
              System.out.println(future2.get());
          }
      }
      
  2. 数据库查询和处理:

    • 可以异步查询数据库,并在查询结果上进行进一步的处理。
    • 示例:
      import java.sql.Connection;
      import java.sql.DriverManager;
      import java.sql.ResultSet;
      import java.sql.SQLException;
      import java.sql.Statement;
      import java.util.concurrent.CompletableFuture;
      
      public class DatabaseExample {
          public static CompletableFuture<Integer> queryDatabase() {
              return CompletableFuture.supplyAsync(() -> {
                  try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "username", "password");
                       Statement statement = connection.createStatement();
                       ResultSet resultSet = statement.executeQuery("SELECT COUNT(*) FROM mytable")) {
      
                      if (resultSet.next()) {
                          return resultSet.getInt(1);
                      } else {
                          return 0;
                      }
                  } catch (SQLException e) {
                      throw new RuntimeException(e);
                  }
              });
          }
      
          public static void main(String[] args) throws Exception {
              CompletableFuture<Integer> future = queryDatabase();
              Integer result = future.get();
              System.out.println("Number of rows in the table: " + result);
          }
      }
      
posted @ 2026-07-29 09:44  渔樵江渚  阅读(11)  评论(0)    收藏  举报