异步编程 之 CompletableFuture

Java CompletableFuture 并发编程 API 详解及示例

一、核心特性概述

CompletableFuture 是 Java 8 引入的异步编程框架,实现了 FutureCompletionStage 接口,提供非阻塞回调、链式调用、任务组合和异常处理能力。其核心优势包括:

  • 非阻塞回调:通过回调函数处理结果,避免线程阻塞
  • 链式调用:支持 thenApplythenAccept 等方法串联任务
  • 任务组合:提供 thenCombineallOf 等方法合并多个任务
  • 异常处理:支持 exceptionallyhandle 等方法统一处理异常

二、核心 API 分类详解

1. 创建异步任务

(1) supplyAsync / runAsync

// 创建带返回值的异步任务(默认使用 ForkJoinPool.commonPool())
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    try { Thread.sleep(1000); } catch (InterruptedException e) {}
    return "Hello";
});

// 创建无返回值的异步任务
CompletableFuture<Void> voidFuture = CompletableFuture.runAsync(() -> 
    System.out.println("Running in background thread")
);

// 指定自定义线程池
ExecutorService executor = Executors.newFixedThreadPool(5);
CompletableFuture<String> customFuture = CompletableFuture.supplyAsync(
    () -> "Using custom thread pool", 
    executor
);

(2) completedFuture

// 创建已完成的 CompletableFuture
CompletableFuture<String> immediateFuture = CompletableFuture.completedFuture("Instant Result");

2. 结果处理与转换

(1) 同步转换

// thenApply: 转换结果(有返回值)
CompletableFuture<Integer> lengthFuture = future.thenApply(String::length);

// thenAccept: 消费结果(无返回值)
future.thenAccept(result -> System.out.println("Result: " + result));

// thenRun: 不依赖前序结果执行新任务
future.thenRun(() -> System.out.println("Task completed"));

(2) 异步变体

// thenApplyAsync: 异步转换结果
CompletableFuture<Integer> asyncLengthFuture = future.thenApplyAsync(String::length);

// 指定线程池的异步执行
CompletableFuture<Integer> customAsyncFuture = future.thenApplyAsync(
    String::length, 
    executor
);

3. 任务组合

(1) 双向组合

// thenCombine: 合并两个任务的结果
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);
future1.thenCombine(future2, (a, b) -> a + b)
       .thenAccept(System.out::println); // 输出 30

(2) 多任务组合

// allOf: 等待所有任务完成
CompletableFuture<Void> allFutures = CompletableFuture.allOf(
    CompletableFuture.runAsync(() -> System.out.println("Task 1")),
    CompletableFuture.runAsync(() -> System.out.println("Task 2"))
);
allFutures.thenRun(() -> System.out.println("All tasks completed"));

// anyOf: 任意任务完成时触发
CompletableFuture<Object> anyFuture = CompletableFuture.anyOf(
    CompletableFuture.supplyAsync(() -> "Result 1"),
    CompletableFuture.supplyAsync(() -> "Result 2")
);
anyFuture.thenAccept(System.out::println); // 输出第一个完成的结果

4. 异常处理

(1) exceptionally

CompletableFuture<Integer> failedFuture = CompletableFuture.supplyAsync(() -> {
    throw new RuntimeException("Error");
}).exceptionally(ex -> {
    System.out.println("Exception: " + ex.getMessage());
    return 0;
});

(2) handle

future.handle((result, ex) -> {
    if (ex != null) {
        System.out.println("Error: " + ex.getMessage());
        return -1;
    }
    return result;
});

(3) whenComplete

future.whenComplete((result, ex) -> {
    if (ex != null) System.out.println("Task failed");
});

5. 串行执行链

CompletableFuture.supplyAsync(() -> "Data")
    .thenApply(data -> data + " processed")
    .thenApply(String::toUpperCase)
    .thenAccept(System.out::println); // 输出 "DATA PROCESSED"

三、实战案例

案例1:并行处理电商订单

// 模拟并行处理订单的多个步骤
CompletableFuture<Void> orderProcess = CompletableFuture.runAsync(() -> 
    System.out.println("Processing payment")
);

CompletableFuture<Void> inventoryUpdate = CompletableFuture.runAsync(() -> 
    System.out.println("Updating inventory")
);

CompletableFuture<Void> notification = CompletableFuture.runAsync(() -> 
    System.out.println("Sending notification")
);

// 等待所有任务完成
CompletableFuture.allOf(orderProcess, inventoryUpdate, notification)
    .thenRun(() -> System.out.println("Order completed"));

案例2:异步网络请求处理

// 模拟异步获取数据并处理
CompletableFuture<String> fetchData = CompletableFuture.supplyAsync(() -> {
    try { Thread.sleep(500); } catch (InterruptedException e) {}
    return "Raw Data";
});

fetchData.thenApply(data -> data + " Processed")
         .thenApply(String::toUpperCase)
         .thenAccept(System.out::println); // 输出 "RAW DATA PROCESSED"

案例3:任务超时控制

// 设置任务超时
CompletableFuture<String> timeoutFuture = new CompletableFuture<>();

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.schedule(() -> {
    if (!timeoutFuture.isDone()) {
        timeoutFuture.completeExceptionally(new TimeoutException("Operation timed out"));
    }
}, 3, TimeUnit.SECONDS);

// 正常完成任务
new Thread(() -> {
    try { Thread.sleep(5000); } catch (InterruptedException e) {}
    timeoutFuture.complete("Success");
}).start();

timeoutFuture.exceptionally(ex -> {
    System.out.println("Error: " + ex.getMessage());
    return "Fallback Result";
});

四、最佳实践建议

  1. 线程池选择

    • 默认使用 ForkJoinPool.commonPool()
    • 生产环境建议自定义线程池(如 Executors.newFixedThreadPool()
  2. 异常处理

    • 始终处理 exceptionallyhandle
    • 避免忽略异常导致任务静默失败
  3. 任务依赖

    • 确保任务顺序正确,避免竞态条件
    • 使用 thenCompose 处理嵌套异步任务
  4. 资源释放

    • 长时间运行的任务需考虑线程池关闭
    • 使用 try-with-resources 管理资源
  5. 性能优化

    • 合理设置线程池大小
    • 避免过度细分任务导致调度开销
posted @ 2025-10-17 10:03  蓝迷梦  阅读(63)  评论(0)    收藏  举报