MST

星途 面试题库

面试题:Java中CompletableFuture如何处理异步任务异常

在使用CompletableFuture执行异步任务时,假设任务可能会抛出异常。请描述如何捕获并处理这些异常,同时列举至少两种不同的处理方式,并说明它们之间的区别。
49.7万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. 使用exceptionally方法
    • 代码示例
CompletableFuture.supplyAsync(() -> {
    if (Math.random() < 0.5) {
        throw new RuntimeException("模拟异常");
    }
    return "任务正常完成";
}).exceptionally(ex -> {
    System.out.println("捕获到异常: " + ex.getMessage());
    return "默认值";
}).thenAccept(System.out::println);
  • 处理方式exceptionally方法会在CompletableFuture出现异常时被调用,它接收一个Function,该Function的输入为异常对象,返回值是在出现异常时要返回的替代结果。
  • 特点:它主要用于在异常发生时提供一个备用的结果,适用于需要在异常时返回一个特定值的场景。
  1. 使用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正常完成还是出现异常,都会调用这个BiConsumerBiConsumer的第一个参数是任务正常完成的结果(如果有异常则为null),第二个参数是异常对象(如果任务正常完成则为null)。
  • 特点:它更侧重于对任务完成状态(包括异常情况)的统一处理,不返回新的结果,只是在任务完成(正常或异常)后执行一些操作,比如记录日志等。
  1. 使用handle方法
    • 代码示例
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;
}).thenAccept(System.out::println);
  • 处理方式handle方法接收一个BiFunction,与whenComplete类似,无论任务正常完成还是出现异常都会调用。BiFunction的第一个参数是任务正常完成的结果(如果有异常则为null),第二个参数是异常对象(如果任务正常完成则为null)。handle方法会返回一个新的CompletableFuture,其结果由BiFunction的返回值决定。
  • 特点:它既可以像exceptionally一样在异常时返回备用结果,又能像whenComplete那样对任务的正常和异常情况进行统一处理,灵活性较高。

区别总结:

  • exceptionally专注于异常时提供备用结果。
  • whenComplete侧重于任务完成状态的统一处理,不返回新结果。
  • handle兼具二者特点,既处理任务状态又能返回新结果,灵活性强。