异步编程 之 CompletableFuture
Java CompletableFuture 并发编程 API 详解及示例
一、核心特性概述
CompletableFuture 是 Java 8 引入的异步编程框架,实现了 Future 和 CompletionStage 接口,提供非阻塞回调、链式调用、任务组合和异常处理能力。其核心优势包括:
- 非阻塞回调:通过回调函数处理结果,避免线程阻塞
- 链式调用:支持
thenApply、thenAccept等方法串联任务 - 任务组合:提供
thenCombine、allOf等方法合并多个任务 - 异常处理:支持
exceptionally、handle等方法统一处理异常
二、核心 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";
});
四、最佳实践建议
-
线程池选择:
- 默认使用
ForkJoinPool.commonPool() - 生产环境建议自定义线程池(如
Executors.newFixedThreadPool())
- 默认使用
-
异常处理:
- 始终处理
exceptionally或handle - 避免忽略异常导致任务静默失败
- 始终处理
-
任务依赖:
- 确保任务顺序正确,避免竞态条件
- 使用
thenCompose处理嵌套异步任务
-
资源释放:
- 长时间运行的任务需考虑线程池关闭
- 使用
try-with-resources管理资源
-
性能优化:
- 合理设置线程池大小
- 避免过度细分任务导致调度开销
本文来自博客园,作者:蓝迷梦,转载请注明原文链接:https://www.cnblogs.com/hewei-blogs/articles/19147140

浙公网安备 33010602011771号