CompletableFuture和Future都是Java中的接口,用于异步编程和并发处理。
Future表示一种异步计算的结果,可以通过get()方法获取计算结果或等待计算的完成。但是,如果计算还未完成,get()方法会阻塞线程,这会影响并发性能。此外,Future只能描述单个异步计算过程,无法组合多个任务的结果。
而CompletableFuture是Future的增强版本,在保留Future的基本功能的同时,还提供了更加方便的方法以支持异步操作的组合和链式调用。CompletableFuture可以将多个异步操作组合成一个新的异步计算,并通过回调方式处理结果,无需阻塞线程。
类信息
CompletableFuture
Future
比较
代码展示1
public class FutureExample {
static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(16, 32, 5, TimeUnit.HOURS, new LinkedBlockingQueue<>());
public static void processFutures(List<CompletableFuture<String>> futureList) {
for (CompletableFuture<String> future : futureList) {
// 使用join()方法等待每个Future对象的结果,不会阻塞当前线程
try {
String result = future.join();
// System.out.println("Future result: " + result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
long millis = System.currentTimeMillis();
List<CompletableFuture<String>> futureList = new ArrayList<>();
for (int i = 0; i < 10000000; i++) {
int finalI = i;
futureList.add(CompletableFuture.supplyAsync(() -> ("Result " + finalI)));
}
processFutures(futureList);
System.out.println("join-----------------------" + (System.currentTimeMillis() - millis));
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(15, 50, 5, TimeUnit.HOURS, new LinkedBlockingQueue<>());
long millis2 = System.currentTimeMillis();
List<Future> futures = new ArrayList<>();
for (int i = 0; i < 10000000; i++) {
int finalI = i;
futures.add(threadPool.submit(() -> ("Result " + finalI)));
}
for (Future future : futures) {
Object o = future.get();
// System.out.println(o.toString());
}
System.out.println("get-----------------------" + (System.currentTimeMillis() - millis2));
}
}
结果1
代码展示2
修改线程池的第一个参数为32
结果2
代码展示3
修改线程池的第二个参数为64
结果3
结论
在性能方面,CompletableFuture.join()和Future.get()的速度差异不大。它们都是阻塞方法,会等待异步任务完成并返回结果。具体哪一个更快取决于具体的使用场景和实现方式。
然而,CompletableFuture.join()相对于Future.get()有一个优点,就是它可以更方便地进行异常处理。如果异步任务抛出了异常,CompletableFuture.join()会将异常封装为CompletionException并抛出,而Future.get()则需要在调用get()方法之前显式地调用getException()方法来获取异常信息。
另外,CompletableFuture.join()还可以与其他CompletableFuture实例进行组合操作,实现更为复杂的异步任务处理。而Future.get()则只能用于获取单个异步任务的结果。
综上所述,虽然CompletableFuture.join()和Future.get()在性能上没有明显差异,但是在功能和使用方式上,CompletableFuture.join()更为灵活和方便。