MST

星途 面试题库

面试题:Java CompletableFuture thenApplyAsync 方法的异常处理与链式调用优化

假设有一个复杂的业务场景,需要通过 CompletableFuture 的 thenApplyAsync 方法进行一系列的异步转换操作,形成链式调用。在这个过程中,每个 thenApplyAsync 方法都可能抛出不同类型的异常。请设计一个全面的异常处理机制,确保在链式调用过程中,异常能够被正确捕获、处理和传递,同时优化链式调用的性能,避免不必要的线程切换和资源浪费。请详细说明设计思路并编写相应的Java代码。
11.7万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 异常捕获与处理:在thenApplyAsync链式调用中,使用exceptionally方法来捕获异常。这样可以在每个异步操作抛出异常时,及时捕获并进行处理,避免异常中断整个链式调用。
  2. 异常传递:在exceptionally处理逻辑中,可以选择返回一个默认值或者继续抛出异常,以便上层调用者进一步处理。
  3. 性能优化:合理使用线程池,减少线程创建和销毁带来的开销。避免不必要的线程切换,尽量让任务在同一个线程池中的线程上执行。

Java代码

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class CompletableFutureExceptionHandling {

    private static final ExecutorService executor = Executors.newFixedThreadPool(5);

    public static void main(String[] args) {
        CompletableFuture.supplyAsync(() -> {
            if (Math.random() < 0.5) {
                throw new RuntimeException("模拟异常1");
            }
            return "初始结果";
        }, executor)
       .thenApplyAsync(result -> {
            if (Math.random() < 0.5) {
                throw new IllegalArgumentException("模拟异常2");
            }
            return result + " 处理后";
        }, executor)
       .thenApplyAsync(result -> {
            if (Math.random() < 0.5) {
                throw new NullPointerException("模拟异常3");
            }
            return result + " 再次处理后";
        }, executor)
       .exceptionally(ex -> {
            System.out.println("捕获到异常: " + ex.getMessage());
            // 这里可以选择返回默认值或者继续抛出异常
            return "默认结果";
        })
       .thenAcceptAsync(System.out::println, executor);

        // 关闭线程池
        executor.shutdown();
    }
}

在上述代码中:

  1. CompletableFuture.supplyAsync开启一个异步任务,并在其中模拟可能抛出的异常。
  2. 每个thenApplyAsync方法同样模拟可能抛出不同类型异常的操作。
  3. exceptionally方法捕获链式调用过程中抛出的异常,并进行处理,这里简单打印异常信息并返回默认值。
  4. 使用ExecutorService线程池来执行异步任务,通过合理设置线程池大小来优化性能,同时在程序结束时关闭线程池。