MST

星途 面试题库

面试题:Java中CompletableFuture exceptionally方法在高并发复杂场景下的优化

在高并发且任务依赖关系复杂的场景中,使用CompletableFuture的exceptionally方法处理异常时,可能会面临性能瓶颈或资源浪费等问题。请分析可能出现的问题,并提出至少两种优化方案,同时给出相应的代码示例。
40.1万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

可能出现的问题

  1. 性能瓶颈exceptionally 方法每次都为每个 CompletableFuture 创建一个新的异常处理逻辑,在高并发场景下,频繁创建和调度这些异常处理任务会带来额外的开销,导致性能瓶颈。
  2. 资源浪费:当有大量 CompletableFuture 出现异常时,每个都通过 exceptionally 进行处理,会占用大量的线程资源和内存资源,尤其是当异常处理逻辑较为复杂时,资源浪费更为明显。

优化方案及代码示例

方案一:集中式异常处理

将多个 CompletableFuture 的异常集中到一个地方处理,减少重复的异常处理逻辑创建。

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

public class CompletableFutureExceptionHandling {
    private static final ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) {
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            if (Math.random() > 0.5) {
                throw new RuntimeException("Simulated exception in future1");
            }
            return 10;
        }, executor);

        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            if (Math.random() > 0.5) {
                throw new RuntimeException("Simulated exception in future2");
            }
            return 20;
        }, executor);

        CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2);

        allFutures.join();

        handleExceptions(future1, future2);
    }

    private static void handleExceptions(CompletableFuture<?>... futures) {
        for (CompletableFuture<?> future : futures) {
            if (future.isCompletedExceptionally()) {
                try {
                    future.get();
                } catch (InterruptedException | ExecutionException e) {
                    System.err.println("Caught exception: " + e.getCause());
                }
            }
        }
    }
}

方案二:自定义异常处理策略

创建一个通用的异常处理策略,通过 whenComplete 方法在任务完成(正常或异常)时统一应用该策略。

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.BiConsumer;

public class CustomExceptionHandling {
    private static final ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) {
        BiConsumer<Object, Throwable> exceptionHandler = (result, ex) -> {
            if (ex != null) {
                System.err.println("Caught exception: " + ex.getMessage());
            } else {
                System.out.println("Result: " + result);
            }
        };

        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            if (Math.random() > 0.5) {
                throw new RuntimeException("Simulated exception in future1");
            }
            return 10;
        }, executor);

        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            if (Math.random() > 0.5) {
                throw new RuntimeException("Simulated exception in future2");
            }
            return 20;
        }, executor);

        future1.whenComplete(exceptionHandler);
        future2.whenComplete(exceptionHandler);

        executor.shutdown();
    }
}