MST

星途 面试题库

面试题:Java CompletableFuture exceptionally异常处理在复杂异步任务链中的优化策略

假设存在一个复杂的Java CompletableFuture异步任务链,其中多个环节都可能抛出不同类型的异常,使用exceptionally方法进行异常处理时,如何设计一个高效的异常处理策略,既能保证每个环节异常得到恰当处理,又能避免代码冗余和性能损耗?请结合实际业务场景详细阐述,并给出核心代码示例。
20.7万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

设计高效异常处理策略的思路

  1. 分层处理:根据业务逻辑,将异常处理分为不同层次。例如,底层的技术异常(如网络异常、数据库连接异常)和业务层异常(如参数校验异常、业务规则冲突异常)。
  2. 复用异常处理逻辑:对于相同类型的异常,在不同环节尽量复用相同的处理逻辑,避免重复代码。
  3. 日志记录:在异常处理过程中,详细记录异常信息,方便排查问题。

实际业务场景举例

假设我们有一个电商系统,在用户下单流程中,涉及到库存检查、订单创建、支付处理等异步任务。每个任务都可能抛出不同类型的异常。例如,库存检查可能抛出库存不足异常,支付处理可能抛出支付失败异常。

核心代码示例

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

public class CompletableFutureExceptionHandling {

    public static void main(String[] args) {
        CompletableFuture<Void> future = checkStock()
               .thenCompose(stock -> createOrder(stock))
               .thenCompose(order -> processPayment(order))
               .exceptionally(ex -> {
                    // 处理所有异常的通用逻辑,如记录日志
                    System.err.println("发生异常: " + ex.getMessage());
                    // 根据异常类型进行不同处理
                    if (ex instanceof InsufficientStockException) {
                        handleInsufficientStockException((InsufficientStockException) ex);
                    } else if (ex instanceof PaymentFailedException) {
                        handlePaymentFailedException((PaymentFailedException) ex);
                    }
                    return null;
                });

        try {
            future.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }

    private static CompletableFuture<Integer> checkStock() {
        return CompletableFuture.supplyAsync(() -> {
            // 模拟库存检查
            if (Math.random() < 0.2) {
                throw new InsufficientStockException("库存不足");
            }
            return 10;
        });
    }

    private static CompletableFuture<String> createOrder(int stock) {
        return CompletableFuture.supplyAsync(() -> {
            // 模拟订单创建
            if (Math.random() < 0.1) {
                throw new OrderCreationException("订单创建失败");
            }
            return "订单号: 123456";
        });
    }

    private static CompletableFuture<Void> processPayment(String order) {
        return CompletableFuture.runAsync(() -> {
            // 模拟支付处理
            if (Math.random() < 0.15) {
                throw new PaymentFailedException("支付失败");
            }
            System.out.println("支付成功,订单: " + order);
        });
    }

    private static void handleInsufficientStockException(InsufficientStockException ex) {
        System.err.println("处理库存不足异常: " + ex.getMessage());
        // 例如,通知管理员补货等操作
    }

    private static void handlePaymentFailedException(PaymentFailedException ex) {
        System.err.println("处理支付失败异常: " + ex.getMessage());
        // 例如,重试支付、通知用户等操作
    }

    static class InsufficientStockException extends RuntimeException {
        public InsufficientStockException(String message) {
            super(message);
        }
    }

    static class OrderCreationException extends RuntimeException {
        public OrderCreationException(String message) {
            super(message);
        }
    }

    static class PaymentFailedException extends RuntimeException {
        public PaymentFailedException(String message) {
            super(message);
        }
    }
}

说明

  1. exceptionally方法中,先记录通用的异常日志,然后根据异常类型调用不同的处理方法。
  2. 每个异步任务通过CompletableFuturesupplyAsyncrunAsync方法模拟,并且可能抛出不同类型的异常。
  3. 异常处理方法(如handleInsufficientStockExceptionhandlePaymentFailedException)可以包含具体的业务处理逻辑,如通知管理员、重试操作等。