Java CompletableFuture 使用详解

Java CompletableFuture 使用详解

CompletableFuture 是 Java 8 引入的异步编程工具,它实现了 FutureCompletionStage 接口,提供了强大的异步编程能力。

1. 基础创建方式

java 复制代码
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class CompletableFutureBasics {
    
    // 1. 直接创建已完成的 Future
    public static void completedFutureExample() {
        CompletableFuture<String> future = CompletableFuture.completedFuture("Hello");
        try {
            System.out.println(future.get()); // 输出: Hello
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    // 2. 使用 runAsync 执行无返回值的异步任务
    public static void runAsyncExample() {
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("异步任务执行中...");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步任务完成");
        });
        
        future.join(); // 等待任务完成
    }
    
    // 3. 使用 supplyAsync 执行有返回值的异步任务
    public static void supplyAsyncExample() {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "异步任务结果";
        });
        
        try {
            String result = future.get(); // 阻塞获取结果
            System.out.println("结果: " + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2. 回调处理(链式操作)

java 复制代码
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

public class CallbackExample {
    
    public static void thenApplyExample() {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Hello";
        });
        
        // thenApply: 转换结果
        CompletableFuture<String> greetingFuture = future.thenApply(s -> s + " World");
        
        // thenAccept: 消费结果,无返回值
        greetingFuture.thenAccept(s -> System.out.println("结果: " + s));
        
        // thenRun: 任务完成后执行,不关心结果
        greetingFuture.thenRun(() -> System.out.println("任务完成"));
        
        greetingFuture.join();
    }
    
    public static void thenComposeExample() {
        // thenCompose: 组合两个 Future,第二个依赖于第一个的结果
        CompletableFuture<String> future = getUserInfo("123")
            .thenCompose(user -> getOrderInfo(user));
        
        future.thenAccept(System.out::println).join();
    }
    
    private static CompletableFuture<String> getUserInfo(String userId) {
        return CompletableFuture.supplyAsync(() -> "用户" + userId);
    }
    
    private static CompletableFuture<String> getOrderInfo(String user) {
        return CompletableFuture.supplyAsync(() -> user + "的订单信息");
    }
}

3. 组合多个 Future

java 复制代码
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

public class CombineExample {
    
    public static void thenCombineExample() {
        // thenCombine: 组合两个独立的 Future
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Hello";
        });
        
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "World";
        });
        
        // 组合两个结果
        CompletableFuture<String> combined = future1.thenCombine(future2, (s1, s2) -> s1 + " " + s2);
        
        System.out.println(combined.join()); // 输出: Hello World
    }
    
    public static void allOfExample() {
        // allOf: 等待所有 Future 完成
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "结果1");
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "结果2");
        CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> "结果3");
        
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2, future3);
        
        allFutures.thenRun(() -> {
            try {
                System.out.println("所有任务完成: " + future1.get() + ", " + future2.get() + ", " + future3.get());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).join();
    }
    
    public static void anyOfExample() {
        // anyOf: 任意一个 Future 完成即可
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "结果1";
        });
        
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "结果2";
        });
        
        CompletableFuture<Object> anyFuture = CompletableFuture.anyOf(future1, future2);
        
        System.out.println("最先完成的结果: " + anyFuture.join()); // 输出: 结果2
    }
}

4. 异常处理

java 复制代码
import java.util.concurrent.CompletableFuture;

public class ExceptionHandlingExample {
    
    public static void exceptionallyExample() {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            if (true) {
                throw new RuntimeException("发生异常");
            }
            return "正常结果";
        });
        
        // exceptionally: 发生异常时提供默认值
        CompletableFuture<String> safeFuture = future.exceptionally(ex -> {
            System.out.println("捕获异常: " + ex.getMessage());
            return "默认值";
        });
        
        System.out.println(safeFuture.join()); // 输出: 默认值
    }
    
    public static void handleExample() {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // 这里可能会成功,也可能会失败
            return "正常结果";
            // throw new RuntimeException("发生异常");
        });
        
        // handle: 无论成功还是失败都会执行
        CompletableFuture<String> handledFuture = future.handle((result, ex) -> {
            if (ex != null) {
                return "异常处理结果";
            }
            return "处理后的: " + result;
        });
        
        System.out.println(handledFuture.join());
    }
    
    public static void whenCompleteExample() {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // throw new RuntimeException("测试异常");
            return "成功结果";
        });
        
        // whenComplete: 任务完成后执行,可获取结果和异常
        future.whenComplete((result, ex) -> {
            if (ex != null) {
                System.out.println("任务异常: " + ex.getMessage());
            } else {
                System.out.println("任务成功: " + result);
            }
        }).join();
    }
}

5. 超时处理(Java 9+)

java 复制代码
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class TimeoutExample {
    
    public static void orTimeoutExample() {
        // orTimeout: Java 9+ 的超时方法
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "慢任务结果";
        }).orTimeout(1, TimeUnit.SECONDS) // 设置1秒超时
          .exceptionally(ex -> {
              if (ex instanceof TimeoutException) {
                  return "超时,返回默认值";
              }
              return "其他异常";
          });
        
        System.out.println(future.join()); // 输出: 超时,返回默认值
    }
    
    public static void completeOnTimeoutExample() {
        // completeOnTimeout: 超时时完成并返回默认值
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "慢任务结果";
        }).completeOnTimeout("超时默认值", 1, TimeUnit.SECONDS);
        
        System.out.println(future.join()); // 输出: 超时默认值
    }
}

6. 实际应用示例

java 复制代码
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;

public class PracticalExample {
    
    // 自定义线程池
    private static final ExecutorService executor = Executors.newFixedThreadPool(10);
    
    public static void parallelTasksExample() {
        List<String> ids = List.of("1", "2", "3", "4", "5");
        
        // 并行查询多个ID的信息
        List<CompletableFuture<String>> futures = ids.stream()
            .map(id -> CompletableFuture.supplyAsync(() -> queryDatabase(id), executor))
            .collect(Collectors.toList());
        
        // 等待所有查询完成
        List<String> results = futures.stream()
            .map(CompletableFuture::join)
            .collect(Collectors.toList());
        
        System.out.println("查询结果: " + results);
    }
    
    private static String queryDatabase(String id) {
        try {
            TimeUnit.MILLISECONDS.sleep(500); // 模拟数据库查询
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "数据" + id;
    }
    
    public static void pipelineExample() {
        // 构建处理流水线
        CompletableFuture<String> pipeline = CompletableFuture
            .supplyAsync(() -> "原始数据", executor)
            .thenApplyAsync(data -> data + " -> 步骤1处理", executor)
            .thenApplyAsync(data -> data + " -> 步骤2处理", executor)
            .thenApplyAsync(data -> data + " -> 步骤3处理", executor)
            .thenApplyAsync(data -> data + " -> 完成", executor);
        
        System.out.println("流水线结果: " + pipeline.join());
    }
    
    public static void shutdown() {
        executor.shutdown();
    }
    
    public static void main(String[] args) {
        try {
            parallelTasksExample();
            pipelineExample();
        } finally {
            shutdown();
        }
    }
}

7. 最佳实践

  1. 使用自定义线程池:避免使用默认的 ForkJoinPool,防止影响其他任务
  2. 合理处理异常:使用 exceptionally、handle 等方法处理异常
  3. 避免阻塞:尽量使用 thenApply、thenAccept 等非阻塞方法
  4. 资源清理:及时关闭自定义的 ExecutorService
  5. 避免嵌套过深:保持链式调用的可读性

8. 主要方法总结

方法 描述
supplyAsync() 异步执行有返回值的任务
runAsync() 异步执行无返回值的任务
thenApply() 对结果进行转换
thenAccept() 消费结果,无返回值
thenRun() 任务完成后执行,不关心结果
thenCompose() 组合两个有依赖关系的 Future
thenCombine() 组合两个独立的 Future
allOf() 等待所有 Future 完成
anyOf() 任意一个 Future 完成即可
exceptionally() 异常处理
handle() 处理结果和异常
whenComplete() 完成后执行回调

CompletableFuture 使得异步编程变得更加简洁和强大,是 Java 并发编程中的重要工具。

相关推荐
咩咩啃树皮5 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
鱟鲥鳚6 小时前
Spring Boot 集成 LangChain4j:从模型调用到 Tool Calling(Demo版)
java·spring boot
大模型码小白7 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程
腾渊信息科技公司8 小时前
Spring Boot对接MES实战:视觉检测数据自动同步方案
java·人工智能·spring boot·后端·计算机视觉·ai·软件需求
爱笑的源码基地9 小时前
高并发 Redis 缓存门诊HIS系统源码,含财务统计药房进销存
java·程序·门诊系统·诊所系统·云诊所源码
wuqingshun3141599 小时前
TCP超时重传机制是为了解决什么问题?
java
莫逸风11 小时前
【AgentScope 2.0】 0. 学习指南
java·llm·agent·agentscope
z1234567898612 小时前
2026最新两款AI编程工具深度对比实测
java·数据库·ai编程
yaoxin52112313 小时前
470. Java 反射 - Member 接口与 AccessFlag
java·开发语言·python
做个文艺程序员13 小时前
Linux第24篇:Java应用监控体系搭建:Prometheus+Grafana可视化运维
java·grafana·prometheus