面试题答案
一键面试可能出现的问题
- 性能瓶颈:
exceptionally
方法每次都为每个CompletableFuture
创建一个新的异常处理逻辑,在高并发场景下,频繁创建和调度这些异常处理任务会带来额外的开销,导致性能瓶颈。 - 资源浪费:当有大量
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();
}
}