1. 什么是Future?
在Java中,当一个方法需要一定的时间来执行,而我们不想等待它完成,同时又需要它的结果时,就可以使用Future。Future是一个接口,它表示一个异步计算的结果。我们可以使用它来检查计算是否完成,等待计算的完成,并获取计算的结果。
使用Future的示例:
ExecutorService executor = Executors.newSingleThreadExecutor();
Future futureResult = executor.submit(() -> {
// 执行一些耗时操作
return "result";
});
// 在这里进行其他操作
String result = futureResult.get(); // 阻塞直到异步操作完成,获取结果
上面的示例中,我们使用ExecutorService和submit方法提交了一个异步计算。submit方法返回了一个Future对象,我们可以使用它来获取计算的结果。
2. 什么是CompletableFuture?
CompletableFuture是Java 8中引入的类,它是Future的扩展,提供了对异步计算的支持。与Future不同的是,CompletableFuture具有更加强大和灵活的功能,并且可以链式调用,能够更加方便地处理异步计算结果。
CompletableFuture提供了丰富的API,可以实现异步计算和多个异步计算的组合和转换,同时还能处理异常和取消操作。使用CompletableFuture可以更加简洁和优雅地编写异步代码。
3. CompletableFuture和Future的区别
3.1 异步操作的启动方式
Future:Future的异步操作需要显式地提交到一个ExecutorService中执行,通常使用executor.submit()方法提交一个Callable或Runnable任务。
CompletableFuture:CompletableFuture支持两种异步操作的启动方式:
使用runAsync()或supplyAsync()方法创建一个异步计算任务,并且指定一个线程池来执行任务。
使用CompletableFuture.supplyAsync()或CompletableFuture.runAsync()方法创建一个新的CompletableFuture,并且使用前一个CompletableFuture的计算结果作为参数。
3.2 得到异步计算结果的方式
Future:获取Future的计算结果可以调用Future.get()方法,如果异步计算还没有完成,get()方法会阻塞当前线程,直到异步计算完成。
CompletableFuture:CompletableFuture提供了多个方法获取异步计算结果:
使用get()方法获取计算结果,如果异步计算还没有完成,get()方法会阻塞当前线程。
使用join()方法获取计算结果,它的行为类似于get()方法,但是不会抛出checked异常。
使用whenComplete()、handle()和 exceptionally()方法处理异步计算的结果和异常。
使用thenApply()、thenAccept()和thenRun()方法组合多个异步计算任务。
3.3 处理异常的方式
Future:Future没有提供处理异步计算异常的方法,只有一个get()方法会抛出ExecutionException异常,它将计算过程中抛出的异常包装在其中。
CompletableFuture:CompletableFuture提供了多个方法处理异步计算中的异常,包括:handle()、whenComplete()和 exceptionally()方法。
3.4 链式调用的支持
Future:Future不支持链式调用,不能方便的处理多个异步计算任务的结果。
CompletableFuture:CompletableFuture支持链式调用,它的每个方法都返回一个新的CompletableFuture,可以跟其他方法进行链式调用。
4. 使用CompletableFuture
下面是一个使用CompletableFuture的示例,它展示了如何创建并发执行两个异步计算,并且在两个计算完成后使用它们的结果执行一个异步操作。
CompletableFuture future1 = CompletableFuture.supplyAsync(() -> {
// 异步计算
return 100;
});
CompletableFuture future2 = CompletableFuture.supplyAsync(() -> {
// 异步计算
return 200;
});
CompletableFuture future3 = future1.thenCombineAsync(future2, (result1, result2) -> {
// 组合异步计算的结果
return "result: " + (result1 + result2);
});
String result = future3.join(); // 等待异步操作完成,并获取结果
5. 总结
Future和CompletableFuture都是Java中用于处理异步计算的接口和类。Future提供了对异步计算的基本支持,可以用于检测异步计算的完成,并获取计算的结果。CompletableFuture作为Future的扩展,提供了更加强大和灵活的功能,并且可以链式调用,能够更加方便地处理异步计算结果。
当需要处理更复杂的异步计算场景时,建议使用CompletableFuture,它提供了更加方便和灵活的API,并且能够更好地处理异常和组合多个异步计算任务。