CompletableFuture是Java 8中引入的一个类,位于java.util.concurrent包中。它代表一个异步计算的结果,可以是已完成、正在进行或尚未开始。CompletableFuture的设计灵感来源于函数式编程中的Promises/Futures模式,旨在简化异步编程模型,提高代码的可读性和可维护性1。
基本概念和功能
CompletableFuture提供了一种灵活、类型安全的方式来表达异步操作的生命周期,包括创建、组合、处理结果以及处理异常。其主要功能包括:
- 创建:可以通过
completedFuture(T value)
创建一个已经完成的状态的CompletableFuture,或者通过supplyAsync(Supplier<U> supplier, Executor executor)
和runAsync(Runnable runnable, Executor executor)
异步执行任务。 - 组合:可以使用
thenApply(Function<? super T, ? extends U> fn)
在当前CompletableFuture完成后应用给定的Function处理结果,返回一个新的CompletableFuture;thenAccept(Consumer<? super T> consumer)
用于处理结果但不返回新的CompletableFuture;thenRun(Runnable runnable)
用于在CompletableFuture完成后执行任务12。
历史背景和设计理念
CompletableFuture是对传统Future接口的扩展,旨在提供更灵活、更强大的异步任务处理能力。它实现了Future和CompletionStage接口,支持链式异步任务组合、异常处理和灵活的结果转换。CompletableFuture的设计灵感来源于函数式编程中的Promises/Futures模式,简化了异步编程模型,提高了代码的可读性和可维护性13。
使用案例
1. 基本异步任务
使用 supplyAsync
执行带返回值的异步任务:
public static void main(String[] args) throws Exception {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000); // 模拟耗时操作
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Result from async operation";
});
// 获取结果(阻塞)
String result = future.get();
System.out.println(result); // 输出: Result from async operation
}
2. 无返回值的异步任务
使用 runAsync
执行无返回值的异步任务:
public static void main(String[] args) throws Exception {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task completed");
});
}
3.组合多个 Future(并行执行)
使用 thenCombine
合并两个独立 Future 的结果:
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);
CompletableFuture<Integer> combined = future1.thenCombine(future2, (a, b) -> a + b);
System.out.println(combined.get()); // 输出: 30
}
4. 多个 Future 全部完成后执行
public static void main(String[] args) throws Exception {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello")
.thenApply(result -> result + " World")
.thenApply(result -> result.toUpperCase());
System.out.println(future.get()); // 输出: HELLO WORLD
}
5. 多个 Future 全部完成后执行
使用 allOf
等待所有 Future 完成
CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task1");
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task2");
CompletableFuture<String> task3 = CompletableFuture.supplyAsync(() -> "Task3");
CompletableFuture<Void> allFutures = CompletableFuture.allOf(task1, task2, task3);
// 获取所有结果
CompletableFuture<List<String>> allResults = allFutures.thenApply(v -> {
return Arrays.asList(task1.join(), task2.join(), task3.join());
});
allResults.get().forEach(System.out::println);
// 输出:
// Task1
// Task2
// Task3
6. 任意一个 Future 完成后执行
使用 anyOf
只要有一个 Future 完成就继续:
public static void main(String[] args) throws Exception {
CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> {
try { Thread.sleep(2000); } catch (Exception e) {}
return "Task1";
});
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> {
try { Thread.sleep(1000); } catch (Exception e) {}
return "Task2";
});
CompletableFuture<Object> anyResult = CompletableFuture.anyOf(task1, task2);
System.out.println(anyResult.get()); // 输出: Task2(更快完成)
}
7. 异步回调(非阻塞)
使用 whenComplete
或 handle
在 Future 完成时执行回调:
public static void main(String[] args) throws Exception {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try { Thread.sleep(1000); } catch (Exception e) {}
return "Result";
});
future.whenComplete((result, ex) -> {
if (ex == null) {
System.out.println("Completed: " + result);
} else {
System.out.println("Failed: " + ex.getMessage());
}
});
// 主线程无需等待,可继续执行其他任务
System.out.println("Main thread continues...");
}
8. 自定义线程池
指定线程池执行异步任务:
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(4);
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
return "Async result";
}, executor);
System.out.println(future.get());
executor.shutdown();
}
9. 超时处理
使用 orTimeout
或 completeOnTimeout
设置超时:
public static void main(String[] args) throws Exception {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (Exception e) {
}
return "Result";
});
try {
// 超时1秒,将抛出 TimeoutException
String result = future.orTimeout(2, TimeUnit.SECONDS).get();
System.out.println(result);
} catch (Exception e) {
System.out.println("Operation timed out");
}
}
10.异常处理
使用 exceptionally
处理异常:
public static void main(String[] args) throws Exception {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
if (true) {
throw new RuntimeException("Simulated error");
}
return "Success";
}).exceptionally(ex -> {
System.out.println("Caught exception: " + ex.getMessage());
return "Default Value";
});
System.out.println(future.get()); // 输出: Default Value
}
总结
CompletableFuture
通过链式调用和回调机制,提供了强大的异步编程能力,避免了传统回调地狱的问题。常见用法包括:
- 异步执行任务(
supplyAsync
/runAsync
) - 链式处理结果(
thenApply
/thenAccept
) - 组合多个 Future(
thenCombine
/allOf
/anyOf
) - 异常处理(
exceptionally
) - 非阻塞回调(
whenComplete
/handle
)
合理使用 CompletableFuture
可以显著提升并发程序的可读性和性能。