CompletableFuture和Future
CompletableFuture和Future都是用于异步编程的接口,但它们之间存在一些关键的区别:
1. 功能性:
- Future:提供了基本的异步操作功能,允许一个线程提交一个任务,并在另一个线程中获取结果。它主要提供了cancel、isDone、get等方法,用于取消任务、检查任务是否完成以及获取任务结果。
- CompletableFuture:是Future的增强版,提供了更多的方法来处理异步操作的结果,如thenApply、thenAccept、thenRun等,这些方法可以用来处理任务的结果或者在任务完成后执行额外的逻辑。CompletableFuture还支持组合多个异步操作,以及更复杂的错误处理和转换。
2. 非阻塞性:
- Future:Future的get方法默认是阻塞的,直到任务完成。虽然Future接口提供了isDone方法来检查任务是否完成,但get方法本身并不支持超时参数,这意味着如果任务长时间未完成,调用get的线程可能会无限期地阻塞。
- CompletableFuture:CompletableFuture的join和get方法都支持超时参数,允许在指定的时间内等待任务完成。如果超时时间到了任务还未完成,join会抛出CompletionException,而get会抛出TimeoutException。
3. 链式调用:
- Future:不支持链式调用,即不能直接在Future上链式调用其他异步操作。
- CompletableFuture:支持链式调用,可以在一个CompletableFuture上连续调用多个方法来构建复杂的异步操作链。
4. 组合异步操作:
- Future:不支持直接组合多个异步操作。
- CompletableFuture:支持组合多个异步操作,例如使用thenCompose、thenCombine等方法来组合多个CompletableFuture对象。
5. 异常处理:
- Future:Future的异常处理能力有限,通常需要在调用get方法时捕获ExecutionException。
- CompletableFuture:提供了更丰富的异常处理能力,例如exceptionally和handle方法,可以在异步操作失败时执行自定义的错误处理逻辑。
6. API丰富性:
- Future:API较为简单,主要提供基本的异步操作支持。
- CompletableFuture:API非常丰富,提供了大量方法来支持复杂的异步编程场景。
以下是一些CompletableFuture的实用方法的代码示例:
1. 基本创建方法
// supplyAsync: 异步执行一个返回结果的任务 CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { // 模拟长时间运行的任务 TimeUnit.SECONDS.sleep(1); return "Hello, CompletableFuture!"; }); // 然后使用thenAccept来处理结果 future.thenAccept(result -> System.out.println(result));
2. 组合多个CompletableFuture
// thenCombine: 当两个CompletableFuture都完成时,合并它们的结果 CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10); CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "hello"); future1.thenCombine(future2, (num, str) -> num + str) .thenAccept(result -> System.out.println(result)); // 输出 "10hello"
3. 处理结果和异常
// thenApply: 在CompletableFuture完成后处理结果,并返回一个新的CompletableFuture CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "123") .thenApply(numStr -> Integer.parseInt(numStr) * 2); future.thenAccept(result -> System.out.println(result)); // 输出 246 // exceptionally: 处理异常情况 CompletableFuture<String> failedFuture = CompletableFuture.supplyAsync(() -> { throw new RuntimeException("Error"); }).exceptionally(ex -> "Error occurred"); failedFuture.thenAccept(result -> System.out.println(result)); // 输出 "Error occurred"
4. 选择性执行
// applyToEither: 当任意一个CompletableFuture完成时,执行给定的函数 CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> { TimeUnit.SECONDS.sleep(2); return "First"; }); CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> { TimeUnit.SECONDS.sleep(1); return "Second"; }); CompletableFuture<String> either = CompletableFuture.anyOf(future1, future2) .thenApplyBoth((f1, f2) -> f1 + " and " + f2); either.thenAccept(result -> System.out.println(result)); // 可能输出 "Second and First"
5. 其他实用方法
// runAfterBoth: 当两个CompletableFuture都完成时执行给定的操作 CompletableFuture<Void> futureA = CompletableFuture.runAsync(() -> { System.out.println("Future A running"); }); CompletableFuture<Void> futureB = CompletableFuture.runAsync(() -> { System.out.println("Future B running"); }); futureA.runAfterBoth(futureB, () -> System.out.println("Both A and B finished")); // whenComplete: 在CompletableFuture完成时执行的操作,无论是正常完成还是异常完成 CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello") .whenComplete((result, ex) -> { if (ex != null) { System.out.println("An error occurred: " + ex); } else { System.out.println("Completed with result: " + result); } }); // 输出 "Completed with result: Hello"