什么是 Java 的 CompletableFuture?
什么是 Java 的 CompletableFuture?
回答重点
CompletableFuture 是 Java 8 引入的一个强大的异步编程工具。允许非阻塞地处理异步任务,并且可以通过链式调用组合多个异步操作。
核心特性:
- 异步执行:使用
runAsync() 或 supplyAsync() 方法,可以非阻塞地执行任务。
- 任务的组合:可以使用
thenApply()、thenAccept() 等方法在任务完成后进行后续操作,支持链式调用。
- 异常处理:提供
exceptionally()、handle() 等方法来处理异步任务中的异常。
- 并行任务:支持多个异步任务的组合,如
thenCombine()、allOf() 等方法,可以在多个任务完成后进行操作。
- 非阻塞获取结果:相比
Future,CompletableFuture 支持通过回调函数获取结果,而不需要显式的阻塞等待。
扩展知识
使用示例
创建异步任务:
- runAsync:创建异步任务,不返回结果
- supplyAsync:创建异步任务并返回结果
1 2 3 4 5 6 7 8
| CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> { });
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> { return "Hello, mianshiya.com!"; });
|
任务完成回调:
- thenApply:在任务完成后可以对任务结果进行转换返回
- thenAccept:在任务完成后对结果进行消费,但不返回新结果
- thenRun:在任务完成后执行一个操作,但不需要使用任务结果
1 2 3 4 5 6 7 8 9 10 11 12 13
|
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello") .thenApply(result -> result + " mianshiya.com");
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> "Hello") .thenAccept(result -> System.out.println(result));
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> "Hello") .thenRun(() -> System.out.println("Task finished"));
|
任务组合:
- thenCombine:合并两个 CompletableFuture 的结果。
- thenCompose:将一个 CompletableFuture 的结果作为另一个 CompletableFuture 的输入。
1 2 3 4 5 6 7 8
| CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello"); CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "面试鸭");
CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (result1, result2) -> result1 + " " + result2);
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello") .thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " 面试鸭"));
|
异常处理:
- exceptionally:在任务发生异常时提供默认值。
- handle:在任务完成或发生异常时进行处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { if (true) { throw new RuntimeException("Exception"); } return "Hello"; }).exceptionally(ex -> "面试鸭");
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { if (true) { throw new RuntimeException("Exception"); } return "Hello"; }).handle((result, ex) -> { if (ex != null) { return "Default Value"; } return result; });
|
并行处理:
- allOf:等待多个 CompletableFuture 全部完成
- anyOf:任意一个 CompletableFuture 完成时执行操作
1 2 3 4 5 6 7 8
| CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2); allFutures.thenRun(() -> System.out.println("面试鸭 tasks finished"));
CompletableFuture<Object> anyFuture = CompletableFuture.anyOf(future1, future2); anyFuture.thenAccept(result -> System.out.println("面试鸭 task finished with result: " + result));
|
与 Future 的区别:
Future 是 Java 5 引入的接口,提供了基本的异步处理功能,但它的局限性在于只能通过 get() 方法阻塞获取结果,无法链式调用多个任务,也缺少异常处理机制。
CompletableFuture 是 Future 的增强版,提供了非阻塞的结果处理、任务组合和异常处理,使得异步编程更加灵活和强大。
异步执行自定义线程池
默认情况下,CompletableFuture 使用 ForkJoinPool 作为线程池,可以通过自定义线程池提高性能或满足特定的并发需求。
例如:
1 2
| Executor executor = Executors.newFixedThreadPool(10); CompletableFuture.supplyAsync(() -> "result", executor);
|
异常处理的灵活性:
CompletableFuture 提供了多种处理异常的方式,允许在异步任务中优雅地处理异常,避免代码复杂度提升。常见的异常处理方法有: