面试题答案
一键面试以下是使用CompletableFuture
实现异步任务链并处理异常的关键代码片段及思路解释:
关键代码片段
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureTaskChain {
public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> {
// 第一个子任务
System.out.println("执行第一个子任务");
if (Math.random() < 0.5) {
throw new RuntimeException("第一个子任务异常");
}
return "第一个子任务结果";
})
.thenApply(result1 -> {
// 第二个子任务,依赖第一个子任务的结果
System.out.println("执行第二个子任务,依赖第一个子任务结果: " + result1);
if (Math.random() < 0.5) {
throw new RuntimeException("第二个子任务异常");
}
return "第二个子任务结果";
})
.thenApply(result2 -> {
// 第三个子任务,依赖第二个子任务的结果
System.out.println("执行第三个子任务,依赖第二个子任务结果: " + result2);
return "第三个子任务结果";
})
.exceptionally(ex -> {
// 统一处理异常
System.out.println("捕获到异常: " + ex.getMessage());
return "默认结果";
})
.thenAccept(finalResult -> {
// 最终处理结果
System.out.println("最终结果: " + finalResult);
});
// 防止主线程退出
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
思路解释
-
第一个子任务:
- 使用
CompletableFuture.supplyAsync
方法创建一个异步任务,该任务会在一个新的线程中执行。 - 在任务执行过程中,模拟了可能出现的异常情况(以50%的概率抛出异常)。
- 如果任务成功执行,返回一个结果。
- 使用
-
后续子任务:
- 使用
thenApply
方法来定义依赖前一个任务结果的后续任务。每个thenApply
方法中的函数接收前一个任务的结果作为参数,并返回当前任务的结果。 - 同样,在每个后续任务中也模拟了可能出现的异常情况。
- 使用
-
异常处理:
- 使用
exceptionally
方法来统一处理任务链中任何一个任务抛出的异常。当任务链中的某个任务抛出异常时,exceptionally
方法中的函数会被调用,在这个函数中可以对异常进行处理,并返回一个默认结果,使任务链能够继续执行下去。
- 使用
-
最终结果处理:
- 使用
thenAccept
方法来处理任务链的最终结果。无论任务链是正常完成还是因为异常而结束,都会执行thenAccept
中的操作,打印最终结果。
- 使用
-
防止主线程退出:
- 在
main
方法中使用Thread.sleep
方法来防止主线程过早退出,确保异步任务有足够的时间执行。
- 在