Fork me on GitHub

Java异步编程CompletableFuture

1. 基本概念

1.1. 是什么

  • Java8引入的异步编程工具、支持非阻塞、链式调用、组合异步任务
  • 继承自Future,扩展CompletionStage接口

1.2. 解决什么问题

  • 传统的Future的局限性(阻塞获取结果、无法手动完成、组合能力差)
  • 简化异步编程,避免回调地狱

1.3. 核心接口

  • CompletiongStage:异步的某个节点,可以与其他阶段组合

2.实用总结

2.1.创建

  • 1.创建 CompletableFuture对象
//异步运行一个任务使用CompletableFuture.runAsync方法 没有返回值
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("Hello CompletableFuture!");
        });
        //2.获取结果
        CompletableFuture<String> futureWithStringResult = CompletableFuture.supplyAsync(() -> {
            // 异步运行一个任务并返回结果使用CompletableFuture.supplyAsync方法
            return "Hello CompletableFuture!";
        });
        try {
            System.out.println("result from futureWithStringResult: " + futureWithStringResult.get());
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }

  • 2.同步运行一个任务 CompletableFuture.completedFuture
CompletableFuture<String> completableFuture = CompletableFuture.completedFuture("completableFuture");
        try {
            System.out.println(completableFuture.get());
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }

  • 3.链式调用

    • thenApply():当CompletableFuture完成时,应用一个函数到结果上
     CompletableFuture<String> stringCompletableFuture = CompletableFuture.supplyAsync(() -> "Hello").thenApply(result -> result + " World");
          try {
              System.out.println(stringCompletableFuture.get());
          } catch (InterruptedException | ExecutionException e) {
              throw new RuntimeException(e);
          }
    

    • thenAccept():当CompletableFuture完成时,消费结果
    CompletableFuture.supplyAsync(()->"Hello").thenAccept(System.out::println);
    

    • thenRun():当CompletableFuture完成时,运行一个动作
    CompletableFuture.supplyAsync(() -> "Hello").thenRun(() -> System.out.println("Completed!"));
    

  • 3.组合CompletableFuture

    • thenCombine():组合两个CompletableFuture
     CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
         CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Word");
         future1.thenCombine(future2, (s1, s2) -> s1 + " " + s2).thenAccept(System.out::println);
         //future1.thenCombineAsync(future2, (s1, s2) -> s1 + " " + s2).thenAccept(System.out::println);
    

    • threComose():组合两个CompletableFuture,当第一个完成时,是用其结果来创建第二个CompletableFuture
    CompletableFuture.supplyAsync(() -> "Hello").thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " World by thenCompose")).thenAccept(System.out::println);
    //CompletableFuture.supplyAsync(() -> "Hello").thenComposeAsync(result -> CompletableFuture.supplyAsync(() -> result + " World by thenCompose")).thenAccept(System.out::println);
    

  • 4.异常处理

    • exceptionally():当CompletableFuture完成时,如果内部放生异常,提供一个备用的结果
     CompletableFuture<String> exceptionally = CompletableFuture.supplyAsync(() -> {
             if (true) {
                 throw new RuntimeException("Something went wrong!");
             }
             return "Hello";
         }).exceptionally(e -> "Error" + e.getMessage());
         try {
             System.out.println(exceptionally.get());
         } catch (InterruptedException | ExecutionException e) {
             throw new RuntimeException(e);
         }
    

    • handle():当CompletableFuture完成时,无论是否发生异常,都应用一个函数到结果或者异常上
     CompletableFuture<String> handle = CompletableFuture.supplyAsync(() -> {
             if (true) {
                 throw new RuntimeException("Something went wrong!");
             }
             return "Hello";
         }).handle((result, e) -> {
             if (e != null) {
                 return "Handle Error" + e.getMessage();
             }
             return result;
         });
         try {
             System.out.println(handle.get());
         } catch (ExecutionException | InterruptedException e) {
             throw new RuntimeException(e);
         }
    

  • 5.等待完成

    • join()阻塞当前想成,直到CompletableFuture完成,并返回结果,如果发生异常,则抛出CompletionException异常
     //单个join
          String join = CompletableFuture.supplyAsync(() -> "Hello").join();
          System.out.println(join);
          //多个join
          System.out.println("multiple join");
          List<CompletableFuture<String>> completableFutures = new ArrayList<>();
          for (int i = 0; i < 10; i++) {
              final int index = i;
              completableFutures.add(CompletableFuture.supplyAsync(() -> {
                  // 业务处理
                  return "Hello " + index;
              }));
          }
          completableFutures.stream().map(CompletableFuture::join).forEach(System.out::println);
          System.out.println("completed!");
    

    • get():与join类似,但会抛出InterruptedException和ExecuteException
    System.out.println("single get");
          try {
              String s = CompletableFuture.supplyAsync(() -> "Hello").get();
              System.out.println(s);
          } catch (InterruptedException | ExecutionException e) {
              throw new RuntimeException(e);
          }
    
          System.out.println("multiple get");
          List<CompletableFuture<String>> completableFutures = new ArrayList<>();
          for (int i = 0; i < 10; i++) {
              final int index = i;
              completableFutures.add(CompletableFuture.supplyAsync(() -> "Hello " + index));
          }
          completableFutures.stream().map(item-> {
              try {
                  return item.get();
              } catch (InterruptedException | ExecutionException e) {
                  throw new RuntimeException(e);
              }
          }).forEach(System.out::println);
          System.out.println("completed!");
    

  • 取消任务

    • cancel():尝试取消任务的执行
            CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
              try {
                  // 模拟业务操作
                  Thread.sleep(3 * 1000);
              } catch (InterruptedException e) {
                  throw new RuntimeException(e);
              }
    
              return "Hello";
          });
          future.handle((result,e)->{
              if(e!=null){
                 e.printStackTrace();
              }
              return result;
          });
          boolean canceled = future.cancel(true);
          System.out.println(canceled);
          try {
              Thread.sleep(10*1000);
          } catch (InterruptedException e) {
              throw new RuntimeException(e);
          }
    


    以上就是CompleteFuture常用的一些方法

posted @ 2025-03-02 13:10  黄高林  阅读(93)  评论(0)    收藏  举报