MST

星途 面试题库

面试题:Java CompletableFuture thenApply 方法的异常处理

在使用 CompletableFuture 的 thenApply 方法时,如果异步任务抛出异常,应该如何优雅地处理?请详细阐述处理机制,并通过代码示例展示如何捕获和处理 thenApply 链中可能出现的异常,同时要说明不同处理方式对程序流程的影响。
25.1万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. 处理机制
    • CompletableFuturethenApply链中,如果前面的异步任务抛出异常,thenApply不会直接捕获这个异常。但是可以通过exceptionally方法来优雅地处理异常。exceptionally方法会在CompletableFuture处于异常完成状态时被调用,它接收一个Function作为参数,该Function的输入是异常,返回值是在异常情况下要返回的结果,从而可以在异常发生时进行补救操作。
  2. 代码示例
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class CompletableFutureExceptionHandling {
    public static void main(String[] args) {
        CompletableFuture.supplyAsync(() -> {
            if (Math.random() > 0.5) {
                throw new RuntimeException("模拟异常");
            }
            return "正常结果";
        })
       .thenApply(result -> {
            System.out.println("处理正常结果: " + result);
            return result.toUpperCase();
        })
       .exceptionally(ex -> {
            System.out.println("捕获到异常: " + ex.getMessage());
            return "异常时的默认结果";
        })
       .thenAccept(System.out::println);


        try {
            // 如果没有使用exceptionally处理异常,这里会抛出异常
            String result = CompletableFuture.supplyAsync(() -> {
                throw new RuntimeException("模拟未处理异常");
            })
           .thenApply(String::toUpperCase)
           .get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}
  1. 不同处理方式对程序流程的影响
    • 使用exceptionally处理异常:程序流程不会被中断,exceptionally捕获异常后返回一个默认值或进行其他补救操作,后续的thenApplythenAccept等方法依然可以按照顺序执行,程序可以继续进行后续逻辑。例如上述代码中,即使前面抛出异常,exceptionally返回默认结果后,thenAccept依然会打印这个结果。
    • 不使用exceptionally处理异常:如果异步任务抛出异常且没有使用exceptionally处理,那么当调用get方法获取结果时,会抛出ExecutionExceptionInterruptedException(如果线程在等待过程中被中断),程序流程会被中断,后续代码无法正常执行,需要在调用处捕获并处理这些异常,否则程序可能会崩溃。