面试题答案
一键面试CompletableFuture链式调用处理异步任务
CompletableFuture可以通过一系列的方法进行链式调用,以处理一系列异步任务。例如:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureExample {
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture.supplyAsync(() -> {
// 第一个异步任务
System.out.println("执行任务1");
return "任务1结果";
})
.thenApply(result1 -> {
// 依赖任务1结果的任务2
System.out.println("执行任务2,依赖任务1结果: " + result1);
return "任务2结果";
})
.thenAccept(result2 -> {
// 依赖任务2结果,不返回值的任务3
System.out.println("执行任务3,依赖任务2结果: " + result2);
})
.exceptionally(ex -> {
// 处理异常
System.out.println("发生异常: " + ex.getMessage());
return null;
});
}
}
在上述代码中,supplyAsync
开启一个异步任务,thenApply
基于前一个任务的结果进行新的计算,thenAccept
用于接收前一个任务的结果但不返回新值,exceptionally
用于处理整个链式调用过程中可能出现的异常。
相比Future的优势
- 多个任务依赖: Future处理多个有依赖关系的任务比较繁琐,通常需要手动阻塞等待前一个任务完成获取结果后才能开始下一个任务。而CompletableFuture可以通过链式调用轻松处理这种情况。例如上面的代码,任务2依赖任务1的结果,任务3依赖任务2的结果,通过链式调用自然衔接。
- 并行任务合并结果:
CompletableFuture提供了
allOf
和anyOf
等方法来合并多个并行任务的结果。例如:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureParallelExample {
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务1执行");
return "任务1结果";
});
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务2执行");
return "任务2结果";
});
CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2);
allFutures.join();// 等待所有任务完成
String result1 = future1.get();
String result2 = future2.get();
System.out.println("合并结果: " + result1 + " " + result2);
}
}
在上述代码中,allOf
方法可以等待所有并行任务完成,然后可以获取每个任务的结果进行合并处理。而Future没有类似简洁的方法来合并多个并行任务的结果,通常需要手动管理线程和同步机制来实现。
综上所述,CompletableFuture在处理复杂异步任务场景下比Future更灵活、简洁,代码可读性更高。