MST

星途 面试题库

面试题:Java CompletableFuture中exceptionally方法的异常处理与whenComplete的区别

在Java的CompletableFuture中,exceptionally方法和whenComplete方法都能处理异常相关情况,请详细说明它们在异常处理机制、使用场景以及对任务结果处理方式上的区别,并通过代码示例进行对比。
48.3万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

异常处理机制区别

  • exceptionally:主要用于捕获并处理CompletableFuture执行过程中抛出的异常。它接收一个Function作为参数,该Function的输入为异常,返回值为当异常发生时的替代结果。如果CompletableFuture正常完成,exceptionally方法不会执行。
  • whenComplete:无论CompletableFuture正常完成还是发生异常,都会执行。它接收一个BiConsumer作为参数,该BiConsumer的两个参数分别为任务结果(如果正常完成)和异常(如果发生异常)。但是whenComplete不能改变任务的最终结果,它只是用于执行一些最终的操作,如日志记录等。

使用场景区别

  • exceptionally:适用于需要在异常发生时提供一个替代结果的场景,比如在远程调用失败时返回一个本地缓存的数据。
  • whenComplete:适用于无论任务成功或失败都需要执行一些通用操作的场景,比如记录任务执行的状态和结果。

对任务结果处理方式区别

  • exceptionally:可以返回一个新的结果来替代异常情况下的原结果,改变任务的最终输出。
  • whenComplete:不能改变任务的最终结果,只是在任务结束时进行一些额外操作。

代码示例对比

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class CompletableFutureExceptionHandling {
    public static void main(String[] args) {
        // 使用exceptionally方法
        CompletableFuture.supplyAsync(() -> {
            if (Math.random() < 0.5) {
                throw new RuntimeException("模拟异常");
            }
            return "正常结果";
        }).exceptionally(ex -> {
            System.out.println("捕获到异常: " + ex.getMessage());
            return "异常替代结果";
        }).thenAccept(System.out::println);

        // 使用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);
            }
        }).thenApply(result -> {
            // 这里不能改变最终结果,因为whenComplete不能改变任务结果
            return result;
        }).thenAccept(System.out::println);

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

在上述代码中,exceptionally方法在异常发生时返回了替代结果并打印。whenComplete方法只是打印了任务的状态(正常或异常),不能改变任务最终结果。