一、CompletableFuture 概述
1.1 什么是 CompletableFuture?
CompletableFuture 是 Java 8 引入的异步编程工具,实现了 Future 和 CompletionStage 接口。它提供了强大的异步编程能力,支持函数式编程风格,可以方便地组合多个异步操作。
1.2 核心特性
-
异步执行:支持异步任务执行
-
链式调用:可以串联多个异步操作
-
组合操作:支持多个异步任务的组合(AND、OR)
-
异常处理:提供完善的异常处理机制
-
手动完成:可以手动完成 Future
二、基本使用方式
2.1 创建 CompletableFuture
java
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CompletableFutureBasic {
// 1. 使用默认线程池创建
public static void createFuture() {
// 有返回值的异步任务
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Hello from async task";
});
// 无返回值的异步任务
CompletableFuture<Void> runFuture = CompletableFuture.runAsync(() -> {
System.out.println("Task is running...");
});
}
// 2. 使用自定义线程池
public static void createWithCustomExecutor() {
ExecutorService executor = Executors.newFixedThreadPool(5);
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// 长时间运行的任务
return "Result";
}, executor);
executor.shutdown();
}
}
三、核心方法详解
3.1 结果处理
java
public class ResultHandling {
// thenApply: 转换结果
public static void thenApplyExample() throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello")
.thenApply(s -> s + " World")
.thenApply(String::toUpperCase);
System.out.println(future.get()); // 输出: HELLO WORLD
}
// thenAccept: 消费结果
public static void thenAcceptExample() {
CompletableFuture.supplyAsync(() -> "Hello")
.thenAccept(result -> System.out.println("Result: " + result));
}
// thenRun: 完成后执行操作
public static void thenRunExample() {
CompletableFuture.supplyAsync(() -> {
System.out.println("Task executing...");
return "Done";
}).thenRun(() -> System.out.println("Task completed"));
}
// handle: 处理结果和异常
public static void handleExample() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
if (true) {
throw new RuntimeException("Error!");
}
return 10;
}).handle((result, ex) -> {
if (ex != null) {
System.out.println("Exception occurred: " + ex.getMessage());
return -1; // 返回默认值
}
return result;
});
System.out.println(future.get()); // 输出: -1
}
// exceptionally: 异常处理
public static void exceptionallyExample() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException("Calculation error");
}).exceptionally(ex -> {
System.err.println("Error: " + ex.getMessage());
return 0; // 返回默认值
});
System.out.println(future.get()); // 输出: 0
}
}
3.2 组合多个 Future
java
public class CombineFutures {
// thenCompose: 链式组合(上一个结果作为下一个的输入)
public static void thenComposeExample() throws ExecutionException, InterruptedException {
CompletableFuture<String> future = getUserInfo(1)
.thenCompose(userId -> getUserDetails(userId));
System.out.println(future.get());
}
// thenCombine: 合并两个独立 Future 的结果
public static void thenCombineExample() throws ExecutionException, InterruptedException {
CompletableFuture<Double> priceFuture = getPrice();
CompletableFuture<Double> taxRateFuture = getTaxRate();
CompletableFuture<Double> totalFuture = priceFuture.thenCombine(
taxRateFuture, (price, taxRate) -> price * (1 + taxRate)
);
System.out.println("Total price: " + totalFuture.get());
}
// allOf: 等待所有 Future 完成
public static void allOfExample() throws ExecutionException, InterruptedException {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Result1");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Result2");
CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> "Result3");
CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2, future3);
allFutures.thenRun(() -> {
try {
System.out.println("All completed: " + future1.get() + ", "
+ future2.get() + ", " + future3.get());
} catch (Exception e) {
e.printStackTrace();
}
}).get();
}
// anyOf: 任意一个完成即可
public static void anyOfExample() throws ExecutionException, InterruptedException {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
sleep(2000);
return "Result1";
});
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
sleep(1000);
return "Result2";
});
CompletableFuture<Object> anyFuture = CompletableFuture.anyOf(future1, future2);
System.out.println("First completed: " + anyFuture.get()); // 输出: Result2
}
// 辅助方法
private static CompletableFuture<String> getUserInfo(int id) {
return CompletableFuture.supplyAsync(() -> "User" + id);
}
private static CompletableFuture<String> getUserDetails(String userId) {
return CompletableFuture.supplyAsync(() -> "Details for " + userId);
}
private static CompletableFuture<Double> getPrice() {
return CompletableFuture.supplyAsync(() -> 100.0);
}
private static CompletableFuture<Double> getTaxRate() {
return CompletableFuture.supplyAsync(() -> 0.1);
}
private static void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
四、实际场景使用案例
4.1 场景一:并行调用多个微服务
java
public class MicroserviceIntegration {
/**
* 电商订单处理:并行获取用户信息、商品信息、库存信息
*/
public CompletableFuture<OrderResult> processOrderAsync(String orderId) {
// 并行调用多个服务
CompletableFuture<UserInfo> userFuture = getUserInfoAsync(orderId);
CompletableFuture<ProductInfo> productFuture = getProductInfoAsync(orderId);
CompletableFuture<InventoryInfo> inventoryFuture = getInventoryInfoAsync(orderId);
// 合并所有结果
return CompletableFuture.allOf(userFuture, productFuture, inventoryFuture)
.thenApply(v -> {
try {
UserInfo user = userFuture.get();
ProductInfo product = productFuture.get();
InventoryInfo inventory = inventoryFuture.get();
return new OrderResult(user, product, inventory);
} catch (Exception e) {
throw new CompletionException(e);
}
})
.exceptionally(ex -> {
// 统一异常处理
log.error("Order processing failed", ex);
return OrderResult.failed(ex.getMessage());
});
}
private CompletableFuture<UserInfo> getUserInfoAsync(String orderId) {
return CompletableFuture.supplyAsync(() -> {
// 模拟调用用户服务
sleep(200);
return new UserInfo("user123", "John Doe");
});
}
private CompletableFuture<ProductInfo> getProductInfoAsync(String orderId) {
return CompletableFuture.supplyAsync(() -> {
// 模拟调用商品服务
sleep(150);
return new ProductInfo("product456", "Laptop", 999.99);
});
}
private CompletableFuture<InventoryInfo> getInventoryInfoAsync(String orderId) {
return CompletableFuture.supplyAsync(() -> {
// 模拟调用库存服务
sleep(100);
return new InventoryInfo("product456", 10);
});
}
// 数据类
static class OrderResult {
UserInfo user;
ProductInfo product;
InventoryInfo inventory;
// 构造方法、getter/setter...
}
}
4.2 场景二:超时控制和回退
java
public class TimeoutAndFallback {
/**
* 带超时和降级的服务调用
*/
public CompletableFuture<String> callServiceWithTimeout() {
ExecutorService executor = Executors.newFixedThreadPool(2);
// 主服务调用
CompletableFuture<String> mainService = CompletableFuture.supplyAsync(() -> {
sleep(3000); // 模拟慢服务
return "Main Service Response";
}, executor);
// 超时控制
CompletableFuture<String> timeout = CompletableFuture.supplyAsync(() -> {
sleep(2000);
return "Timeout Fallback";
}, executor);
// 使用 applyToEither 实现超时控制
return mainService.applyToEither(timeout, response -> {
if (response.equals("Timeout Fallback")) {
// 调用降级服务
return callFallbackService();
}
return response;
});
}
/**
* 使用 CompletableFuture 原生超时(Java 9+)
*/
public CompletableFuture<String> callWithTimeoutJava9() {
return CompletableFuture.supplyAsync(() -> {
sleep(3000);
return "Service Response";
})
.orTimeout(2, TimeUnit.SECONDS) // Java 9+ 方法
.exceptionally(ex -> callFallbackService());
}
private String callFallbackService() {
return "Fallback Service Response";
}
}
4.3 场景三:批量异步处理
java
public class BatchProcessing {
/**
* 批量异步处理数据
*/
public CompletableFuture<List<ProcessResult>> batchProcess(List<String> dataList) {
List<CompletableFuture<ProcessResult>> futures = dataList.stream()
.map(this::processSingleItemAsync)
.collect(Collectors.toList());
// 转换 List<CompletableFuture<T>> 为 CompletableFuture<List<T>>
return sequence(futures);
}
/**
* 限制并发数的批量处理
*/
public CompletableFuture<List<ProcessResult>> batchProcessWithLimit(
List<String> dataList, int maxConcurrency) {
ExecutorService limitedExecutor = Executors.newFixedThreadPool(maxConcurrency);
List<CompletableFuture<ProcessResult>> futures = dataList.stream()
.map(data -> CompletableFuture.supplyAsync(
() -> processItem(data), limitedExecutor))
.collect(Collectors.toList());
limitedExecutor.shutdown();
return sequence(futures);
}
/**
* 将 List<CompletableFuture<T>> 转换为 CompletableFuture<List<T>>
*/
private <T> CompletableFuture<List<T>> sequence(List<CompletableFuture<T>> futures) {
CompletableFuture<Void> allDoneFuture =
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
return allDoneFuture.thenApply(v ->
futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList())
);
}
private ProcessResult processItem(String data) {
// 处理单个数据项
return new ProcessResult(data, "processed");
}
}
4.4 场景四:流水线处理
java
public class PipelineProcessing {
/**
* 数据处理流水线:下载 -> 转换 -> 存储 -> 通知
*/
public CompletableFuture<Void> dataProcessingPipeline(String url) {
return downloadData(url)
.thenApplyAsync(this::transformData, getTransformExecutor())
.thenComposeAsync(this::storeData, getIOWriterExecutor())
.thenAcceptAsync(this::sendNotification, getNotificationExecutor())
.exceptionally(ex -> {
log.error("Pipeline failed", ex);
sendAlert(ex);
return null;
});
}
private CompletableFuture<String> downloadData(String url) {
return CompletableFuture.supplyAsync(() -> {
// 模拟下载
return "Downloaded data from " + url;
});
}
private String transformData(String data) {
// 数据转换
return data.toUpperCase();
}
private CompletableFuture<String> storeData(String data) {
return CompletableFuture.supplyAsync(() -> {
// 模拟存储
return "Stored: " + data;
});
}
private void sendNotification(String result) {
System.out.println("Notification: " + result);
}
private void sendAlert(Throwable ex) {
System.err.println("Alert: " + ex.getMessage());
}
// 不同阶段使用不同的线程池
private ExecutorService getTransformExecutor() {
return Executors.newFixedThreadPool(4);
}
private ExecutorService getIOWriterExecutor() {
return Executors.newFixedThreadPool(2);
}
private ExecutorService getNotificationExecutor() {
return Executors.newSingleThreadExecutor();
}
}
五、最佳实践和注意事项
5.1 最佳实践
java
public class BestPractices {
// 1. 始终处理异常
public void alwaysHandleExceptions() {
CompletableFuture.supplyAsync(() -> {
// 业务逻辑
return "result";
})
.exceptionally(ex -> {
log.error("Task failed", ex);
return "fallback";
});
}
// 2. 使用合适的线程池
public void useProperThreadPool() {
ExecutorService cpuBoundExecutor = Executors.newFixedThreadPool(
Runtime.getRuntime().availableProcessors()
);
ExecutorService ioBoundExecutor = Executors.newCachedThreadPool();
// CPU 密集型任务
CompletableFuture.supplyAsync(() -> {
// 复杂计算
return compute();
}, cpuBoundExecutor);
// IO 密集型任务
CompletableFuture.supplyAsync(() -> {
// 数据库查询
return queryDatabase();
}, ioBoundExecutor);
}
// 3. 避免阻塞调用
public CompletableFuture<String> avoidBlockingCalls() {
return CompletableFuture.supplyAsync(() -> {
// 错误的做法:在异步任务中阻塞
// return blockingHttpCall();
// 正确的做法:使用异步客户端
return asyncHttpClient.get();
});
}
// 4. 资源清理
public void cleanupResources() {
ExecutorService executor = Executors.newFixedThreadPool(5);
try {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
return "result";
}, executor);
String result = future.get(10, TimeUnit.SECONDS);
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
} finally {
executor.shutdown();
try {
if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
}
}
}
}
5.2 常见陷阱
java
public class CommonPitfalls {
// 1. 忘记调用 get() 或 join()
public void pitfall1() {
CompletableFuture.runAsync(() -> {
System.out.println("Task executed");
});
// 如果不调用 get() 或 join(),程序可能直接退出
}
// 2. 在回调中阻塞
public void pitfall2() {
CompletableFuture.supplyAsync(() -> "data")
.thenApply(data -> {
// 错误的做法:在回调中进行阻塞操作
try {
Thread.sleep(5000); // 阻塞!
} catch (InterruptedException e) {
e.printStackTrace();
}
return data.toUpperCase();
});
}
// 3. 异常处理不当
public void pitfall3() {
CompletableFuture.supplyAsync(() -> {
throw new RuntimeException("Error");
}).thenAccept(result -> {
// 这里不会执行,因为异常没有被处理
System.out.println(result);
});
}
// 4. 线程池资源泄露
public void pitfall4() {
ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < 1000; i++) {
CompletableFuture.runAsync(() -> {
// 任务
}, executor);
}
// 忘记关闭线程池!
}
}
六、性能监控和调试
java
public class CompletableFutureMonitor {
private static final ThreadLocal<Long> startTime = new ThreadLocal<>();
/**
* 带监控的 CompletableFuture
*/
public static <T> CompletableFuture<T> monitoredSupplyAsync(
Supplier<T> supplier, String taskName) {
return CompletableFuture.supplyAsync(() -> {
startTime.set(System.currentTimeMillis());
try {
T result = supplier.get();
long duration = System.currentTimeMillis() - startTime.get();
logMetrics(taskName, duration, "SUCCESS");
return result;
} catch (Exception e) {
long duration = System.currentTimeMillis() - startTime.get();
logMetrics(taskName, duration, "FAILED");
throw new CompletionException(e);
} finally {
startTime.remove();
}
});
}
private static void logMetrics(String taskName, long duration, String status) {
System.out.printf("Task: %s, Duration: %dms, Status: %s%n",
taskName, duration, status);
}
/**
* 使用示例
*/
public void example() {
monitoredSupplyAsync(() -> {
sleep(100);
return "Result";
}, "dataProcessing").thenAccept(result -> {
System.out.println("Got result: " + result);
});
}
}
总结
CompletableFuture 提供了强大的异步编程能力,适用于:
-
微服务调用:并行调用多个服务
-
数据处理流水线:链式处理数据
-
批量处理:并发处理大量任务
-
超时控制:实现服务降级和熔断
-
事件驱动架构:响应式编程
关键要点:
-
合理使用线程池,区分 CPU 密集和 IO 密集任务
-
始终处理异常,避免异常被吞没
-
注意资源清理,避免内存泄漏
-
使用适当的超时控制
-
监控异步任务的执行情况
通过合理使用 CompletableFuture,可以显著提升系统的并发性能和响应能力,同时保持代码的可读性和可维护性。