在 Java 8 引入了 CompletableFuture 类后,异步编程变得异常方便。它不但支持链式调用,还能处理结果、异常和组合任务。下面通过一个完整的示例来演示如何使用 CompletableFuture 做异步网络请求、并行计算以及错误回退。
1. 基础使用:完成一个异步任务
CompletableFuture <String> future =
CompletableFuture.supplyAsync(() -> {
// 模拟耗时操作,例如远程调用
try { Thread.sleep(2000); } catch (InterruptedException e) { }
return "Hello, CompletableFuture!";
});
future.thenAccept(result -> System.out.println("获取结果:" + result));
supplyAsync通过默认的 ForkJoinPool.commonPool() 线程池异步执行。thenAccept用于消费结果,返回void。
2. 结果转换与链式调用
CompletableFuture <String> future =
CompletableFuture.supplyAsync(() -> "Java")
.thenApply(name -> name + " 8")
.thenApply(name -> name + " CompletableFuture")
.thenApply(name -> name + " 学习");
future.thenAccept(System.out::println);
使用 thenApply 对结果做映射,形成链式转换,最终打印完整字符串。
3. 异常处理
CompletableFuture <Integer> future =
CompletableFuture.supplyAsync(() -> {
if (new Random().nextBoolean()) throw new RuntimeException("偶发错误");
return 42;
});
future.handle((result, ex) -> {
if (ex != null) {
System.out.println("异常:" + ex.getMessage());
return -1; // 退回默认值
}
return result;
}).thenAccept(System.out::println);
handle无论成功还是异常都会执行,能够统一处理结果与错误。- 如果你只想捕获异常,可以使用
exceptionally。
4. 并行任务组合
假设你需要同时请求用户信息、订单列表和推荐商品,三者之间没有先后关系,可并行执行后统一处理。
CompletableFuture <User> userFuture = CompletableFuture.supplyAsync(() -> fetchUser());
CompletableFuture<List<Order>> orderFuture = CompletableFuture.supplyAsync(() -> fetchOrders());
CompletableFuture<List<Product>> productFuture = CompletableFuture.supplyAsync(() -> fetchRecommendations());
CompletableFuture <Void> combinedFuture = CompletableFuture.allOf(userFuture, orderFuture, productFuture);
combinedFuture.thenRun(() -> {
try {
User user = userFuture.join();
List <Order> orders = orderFuture.join();
List <Product> products = productFuture.join();
System.out.println("用户:" + user);
System.out.println("订单:" + orders);
System.out.println("推荐:" + products);
} catch (CompletionException e) {
System.err.println("组合任务中出现错误:" + e.getCause());
}
});
allOf等待所有任务完成。join用于获取结果,若出现异常会抛出CompletionException。
5. 受限并发:限制线程数
若你想用 CompletableFuture 但不想让所有任务同时跑到线程池(例如限制并发数为 5),可以配合 Executor:
Executor limitedExecutor = Executors.newFixedThreadPool(5);
CompletableFuture <Void> all =
CompletableFuture.allOf(
tasks.stream()
.map(task -> CompletableFuture.runAsync(task, limitedExecutor))
.toArray(CompletableFuture[]::new)
);
6. 结合 Spring Boot
在 Spring Boot 项目中,可以通过 @Async 注解和 AsyncTaskExecutor 配合 CompletableFuture 使用。
@Service
public class AsyncService {
@Async("taskExecutor")
public CompletableFuture <String> asyncMethod() {
// 业务逻辑
return CompletableFuture.completedFuture("async result");
}
}
在配置类里:
@Bean(name = "taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(50);
executor.setThreadNamePrefix("async-");
executor.initialize();
return executor;
}
然后在调用方:
@Autowired
AsyncService asyncService;
public void useAsync() {
CompletableFuture <String> future = asyncService.asyncMethod();
future.thenAccept(result -> System.out.println(result));
}
7. 小结
- CompletableFuture 让异步编程像流式处理一样简洁。
supplyAsync/thenApply/thenAccept形成基础链式调用。handle/exceptionally用于异常统一处理。allOf/anyOf用于任务组合与同步。- 可与自定义
Executor配合控制并发度。 - 在 Spring Boot 中可以结合
@Async提升可维护性。
掌握以上几种用法后,你就能在 Java 项目中轻松实现高并发、低阻塞的异步处理方案。

发表回复