MST

星途 面试题库

面试题:Java CompletableFuture异常处理链的设计与应用

假设有一系列依赖的CompletableFuture任务,前一个任务的结果作为后一个任务的输入,在这个过程中,如果中间某个任务抛出异常,如何设计异常处理链,使得既能处理异常,又能保证其他未出错的任务尽可能继续执行,并最终将所有任务的结果或异常汇总。请详细说明思路并给出示例代码。
47.2万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. 思路
    • 利用CompletableFuture的异常处理方法,如exceptionally来捕获单个任务的异常。
    • 在捕获异常后,可以继续执行后续任务,通过将异常信息作为特殊的“结果”传递给后续任务。
    • 最后,通过joinget方法获取所有任务的最终结果或异常,并进行汇总。
  2. 示例代码
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class CompletableFutureExceptionHandling {
    public static void main(String[] args) {
        List<CompletableFuture<String>> futures = new ArrayList<>();

        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("Task 1 is running");
            return "Result of Task 1";
        });

        CompletableFuture<String> future2 = future1.thenApplyAsync(result -> {
            System.out.println("Task 2 is running with input: " + result);
            if ("Result of Task 1".equals(result)) {
                throw new RuntimeException("Task 2 has an error");
            }
            return "Result of Task 2";
        }).exceptionally(ex -> {
            System.out.println("Task 2 caught an exception: " + ex.getMessage());
            return "Exception in Task 2: " + ex.getMessage();
        });

        CompletableFuture<String> future3 = future2.thenApplyAsync(result -> {
            System.out.println("Task 3 is running with input: " + result);
            return "Result of Task 3";
        });

        futures.add(future1);
        futures.add(future2);
        futures.add(future3);

        List<String> results = new ArrayList<>();
        for (CompletableFuture<String> future : futures) {
            try {
                results.add(future.join());
            } catch (Exception e) {
                results.add("Exception in overall handling: " + e.getMessage());
            }
        }

        System.out.println("Final results: " + results);
    }
}

在上述代码中:

  • future1是第一个任务,正常返回结果。
  • future2依赖future1的结果,这里故意抛出异常,通过exceptionally方法捕获异常并返回包含异常信息的字符串。
  • future3依赖future2的结果,无论future2是正常返回还是抛出异常,都会继续执行。
  • 最后通过遍历futures列表,使用join方法获取每个任务的结果(或异常信息)并汇总到results列表中。