面试题答案
一键面试CompletableFuture处理异常的方法
- exceptionally
- 用法:
CompletableFuture<T> future = CompletableFuture.supplyAsync(() -> { // 模拟可能抛出异常的任务 if (Math.random() > 0.5) { throw new RuntimeException("模拟异常"); } return "任务结果"; }).exceptionally(ex -> { // 捕获异常并返回默认值或处理结果 System.out.println("捕获到异常: " + ex.getMessage()); return "默认结果"; });
- 作用:当
CompletableFuture
的计算过程抛出异常时,exceptionally
方法会捕获该异常,并返回一个替代值。它返回一个新的CompletableFuture
,该CompletableFuture
的结果是原CompletableFuture
正常完成时的结果,或者是异常时传入的替代值。
- 用法:
- handle
- 用法:
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { if (Math.random() > 0.5) { throw new RuntimeException("模拟异常"); } return "任务结果"; }).handle((result, ex) -> { if (ex != null) { System.out.println("捕获到异常: " + ex.getMessage()); return "默认结果"; } return result; });
- 作用:
handle
方法接受一个BiFunction
,它同时处理正常的计算结果和异常情况。无论原CompletableFuture
是正常完成还是异常完成,handle
方法都会被调用,并返回一个新的CompletableFuture
,其结果由BiFunction
的返回值决定。
- 用法:
- whenComplete
- 用法:
CompletableFuture.supplyAsync(() -> { if (Math.random() > 0.5) { throw new RuntimeException("模拟异常"); } return "任务结果"; }).whenComplete((result, ex) -> { if (ex != null) { System.out.println("捕获到异常: " + ex.getMessage()); } else { System.out.println("正常结果: " + result); } });
- 作用:
whenComplete
方法接受一个BiConsumer
,它在CompletableFuture
完成(无论是正常完成还是异常完成)时被调用。它不会改变CompletableFuture
的结果,主要用于执行一些最终的操作,如日志记录等。
- 用法:
优化多步骤异步操作稳定性和可靠性的异常处理策略
- 在有依赖关系任务异常后继续执行后续任务
- 使用
exceptionally
结合thenApply
等方法:例如,假设有两个有依赖关系的任务,任务A执行完后任务B依赖任务A的结果。
- 使用
CompletableFuture<String> taskA = CompletableFuture.supplyAsync(() -> {
if (Math.random() > 0.5) {
throw new RuntimeException("任务A异常");
}
return "任务A结果";
});
CompletableFuture<String> taskB = taskA
.exceptionally(ex -> {
System.out.println("任务A异常: " + ex.getMessage());
return "任务A默认结果";
})
.thenApply(resultA -> {
// 任务B依赖任务A的结果
return "任务B基于 " + resultA + " 的处理结果";
});
- **原理**:`exceptionally`方法捕获任务A的异常并提供默认结果,后续的`thenApply`方法可以基于这个默认结果继续执行任务B,保证了操作链的连续性。
2. 统一捕获和处理整个操作链的异常
- 使用join
或get
方法结合外层try - catch
:
try {
CompletableFuture<String> finalFuture = CompletableFuture.supplyAsync(() -> {
if (Math.random() > 0.5) {
throw new RuntimeException("初始任务异常");
}
return "初始任务结果";
})
.thenApply(result -> {
// 后续任务处理
return "基于初始结果的处理";
});
String result = finalFuture.join();
System.out.println("最终结果: " + result);
} catch (Exception e) {
System.out.println("统一捕获到异常: " + e.getMessage());
}
- **原理**:通过在最外层使用`try - catch`块包裹整个`CompletableFuture`操作链,当调用`join`或`get`方法获取最终结果时,如果操作链中任何一个步骤抛出异常,都会被外层的`catch`块捕获,从而实现统一的异常处理。