在不同的 `ExecutorService` 上执行 `CompletableFuture` 的不同阶段

问题描述 投票:0回答:1

我想要实现的目标:

我想创建一个在 ExecutorService 上运行的 CompletableFuture,然后向其中添加一个在不同 ExecutorService 中执行的阶段。

我尝试过的:

try (ExecutorService benchRunner = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() - 1);
     ExecutorService resultHandler = Executors.newVirtualThreadPerTaskExecutor()) {
    for (Algorithm algorithm : Algorithm.values()) {
        for (Distribution distribution : Distribution.values()) {
            for (Integer arraySize : List.of(30, 60, 90, 300, 600, 900, 3000, 6000, 9000)) {
                SortingBenchmark.Config config = new SortingBenchmark.Config(arraySize, algorithm, distribution);

                CompletableFuture<Benchmark> benchmarkTask = new CompletableFuture<>();
                benchmarkTask.completeAsync(new SortingBenchmark(config), benchRunner);
                benchmarkTask.whenCompleteAsync((b, t) -> {
                    if (t != null) {
                        System.err.println("Failed on: " + config);
                        return;
                    }

                    System.out.println("Finished: " + config);
                }, resultHandler);
            }
        }
    }
}

我的理解是,

whenCompleteAsync
应该在
resultHandler
new SortingBenchmark(config)
上执行之后在
benchRunner
上执行。但是,当我运行它时,
whenCompleteAsync
部分中的代码永远不会运行;然而
completeAsync
部分运行得很好(我可以看出,因为我的 7 个核心固定为 100% 使用率,并且我看到了标准输出)。

如果我向

join
添加
benchmarkTask
调用,
whenCompleteAsync
中的代码开始运行,但这个“解决方案”最终(自然地)导致整个部分变成单线程。

我是否误解了

whenCompleteAsync
的工作原理?我该如何实现我想要的目标?

谢谢,

java concurrency future
1个回答
0
投票

归功于slaw

问题在于 try-with-resources 语句强制对资源调用

close
的顺序进行反向排序;即,最后启动的资源首先被
close
d。

在上面的示例中,这会导致

resultHandler
在提交给
close
的任务完成之前被
benchRunner
处理。

颠倒资源初始化的顺序可以解决该问题。

© www.soinside.com 2019 - 2024. All rights reserved.