What I am trying to achieve:
I want to create a CompletableFuture that runs on an ExecutorService, then add a stage to it that executes in a different ExecutorService.
What I have tried:
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);
}
}
}
}
My understanding is that whenCompleteAsync should execute on resultHandler after new SortingBenchmark(config) executes on benchRunner. However, when I run this, the code in the whenCompleteAsync section never runs; the completeAsync section however runs just fine (I can tell because 7 of my cores are pinned to 100% usage and I see stdout output).
If I add a join call to benchmarkTask, the code in whenCompleteAsync starts to run, but this “solution” ends up (naturally) causing the whole section to become single threaded.
Am I misunderstanding how whenCompleteAsync works? How do I go about achieving what I want?
Thanks,