首页 > 解决方案 > 从 completablefuture 中检索 runnable 的实例

问题描述

我正在运行一个可运行的列表,ExecutorService并使用CompletableFuture. 我想关联CompletableFuture运行特定可运行文件的哪个实例。

这是实际的代码

public static void runTasks(final List<Runnable> tasks, final int threadCount) {
    final ExecutorService es = Executors.newFixedThreadPool(threadCount);
    final CompletableFuture<?>[] futures = tasks.stream()
            .map(task -> CompletableFuture.runAsync(task, es))
            .toArray(CompletableFuture[]::new);
    try {
        CompletableFuture.allOf(futures).join();
        es.shutdown();
    } catch (Exception e) {
        System.exit(1);
    }
}

我将结果存储在期货变量中 CompletableFuture<?>[] futures

有没有办法获取 runnable 的类名,其结果存储在未来的实例中?

我正在尝试按如下方式打印单个任务结果:

for (CompletableFuture future : futures) {
    final boolean taskCompletedSuccessfully = future.isDone() && !(future.isCompletedExceptionally() || future.isCancelled());
    LOGGER.info("Task completion status for {} : {}", <runnable class name>, (taskCompletedSuccessfully ? "SUCCESSFUL" : "FAILED"));
}

标签: javacompletable-future

解决方案


无法检索有关 的任何信息,Runnable因为CompletableFuture不包含对它的任何引用。

因此,您必须在某些实现中将未来和可运行对象(或其类名)存储在一起Pair,例如:

final List<Pair<Runnable, CompletableFuture<Void>>> futures = tasks.stream()
        .map(task -> new Pair<>(task, CompletableFuture.runAsync(task, es)))
        .collect(toList());
try {
    CompletableFuture.allOf(futures.stream().map(Pair::getB).toArray(CompletableFuture[]::new)).join();
} catch (Exception e) {
    log.warn("At least one future failed", e);
}
es.shutdown();
futures.forEach(pair -> {
    CompletableFuture<Void> future = pair.getB();
    final boolean taskCompletedSuccessfully = !future.isCompletedExceptionally();
    log.info("Task completion status for {} : {}", pair.getA().getClass().getSimpleName(), (taskCompletedSuccessfully ? "SUCCESSFUL" : "FAILED"));
});

几点注意事项:

  • 如果任何任务失败,allOf()也将失败。在这种情况下,您可能不希望这样做exit()——否则您将始终只记录成功的任务;
  • 之后allOf().join(),您保证isDone()对所有任务都适用,无需检查;
  • isCancelled()(这里不可能)意味着isCompletedExceptionally()

推荐阅读