MST
星途 面试题库

面试题:Java中CompletableFuture AllOf关系的性能优化

假设存在大量(例如1000个)的CompletableFuture任务通过allOf方法组合,在保证任务逻辑正确执行的前提下,如何对这种场景进行性能优化?请详细阐述优化思路并给出关键代码片段。
29.1万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

优化思路

  1. 任务拆分与并行执行:将大量任务拆分成多个小批次并行执行,减少单个allOf方法处理的任务数量。例如,把1000个任务分成10组,每组100个任务,每组并行执行,然后再对每组的结果进行汇总。
  2. 线程池优化:使用合理配置的线程池,根据系统资源(如CPU核心数、内存等)来设置线程池的大小,避免线程过多导致的上下文切换开销。比如,根据CPU核心数设置线程池大小为Runtime.getRuntime().availableProcessors() * 2
  3. 减少阻塞操作:在任务执行过程中,尽量减少I/O等阻塞操作,若无法避免,可以采用异步I/O方式(如NIO)。
  4. 流处理:利用Java 8的流来处理任务,流的并行处理特性可以提高执行效率。

关键代码片段

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class CompletableFuturePerformanceOptimization {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 线程池配置
        ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);

        // 假设这是要执行的任务列表
        List<CompletableFuture<String>> allTasks = new ArrayList<>();
        IntStream.range(0, 1000).forEach(i -> {
            CompletableFuture<String> task = CompletableFuture.supplyAsync(() -> {
                // 模拟任务执行
                return "Task " + i + " completed";
            }, executor);
            allTasks.add(task);
        });

        // 任务拆分与并行执行
        int batchSize = 100;
        List<CompletableFuture<Void>> batchFutures = new ArrayList<>();
        for (int i = 0; i < allTasks.size(); i += batchSize) {
            List<CompletableFuture<String>> subList = allTasks.subList(i, Math.min(i + batchSize, allTasks.size()));
            CompletableFuture<Void> batchFuture = CompletableFuture.allOf(subList.toArray(new CompletableFuture[0]));
            batchFutures.add(batchFuture);
        }

        // 等待所有批次任务完成
        CompletableFuture<Void> allBatchFuture = CompletableFuture.allOf(batchFutures.toArray(new CompletableFuture[0]));
        allBatchFuture.get();

        // 获取所有任务结果
        List<String> results = allTasks.stream()
               .map(CompletableFuture::join)
               .collect(Collectors.toList());

        results.forEach(System.out::println);

        executor.shutdown();
    }
}

上述代码首先将1000个任务按每100个一批进行拆分,然后并行执行每个批次的任务。通过合理配置线程池,减少了单个allOf处理的任务数量,提高了执行效率。最后获取并打印所有任务的结果。