我需要执行一些额外的任务,但要让原始线程结束,例如发送回HTTP响应。

我想我可以做到这一点:

return mainTasksFuture.thenApply(response -> {
  CompletableFuture.runAsync(() -> {
    // extra tasks
  });
  return response;
});


但是我记得有一个thenRunAsync。是

return mainTasksFuture.thenApply(response -> {
  return response;
}).thenRunAsync(() -> {
  // extra tasks
});


基本上是做同一件事的另一种方法?换句话说,then*Async方法终止符(完成方法)是否在原始线程中返回前一个链的结果,然后生成一个新线程来执行其余的?

我几乎可以肯定,答案是否定的。似乎对于CompletableFutures刚接触的人来说,可能完全基于方法名称。我想得到一个确认,以防万一我读到的关于ForkJoinPool.commonPool的内容实际上以不同的方式表达了我的疑问。

最佳答案

你写了


  似乎只是纯粹基于方法名称,对于CompletableFutures的新手来说。


好吧,方法名称正确地反映了方法的作用。 runAsyncthenRunAsync都启动Runnable的异步执行并返回Future,该异步完成后将完成。因此,名称的相似性是合理的。

根本上是您的代码不同。

在这个变体中

return mainTasksFuture.thenApply(response -> {
  CompletableFuture.runAsync(() -> {
    // extra tasks
  });
  return response;
});


您完全忽略了runAsync返回的将来,因此一旦触发了异步操作,就将完成thenApply返回的将来。当“额外任务”仍在同时运行时,调用方可以检索结果值。

与...相比

    return mainTasksFuture.thenApply(response -> {
        return response;
    }).thenRunAsync(() -> {
      // extra tasks
    });


thenApply完全已作废,因为它没有任何作用。但是您返回的是thenRunAsync返回的将来,当Runnable的异步执行完成并且类型为CompletableFuture<Void>时,它将完成,因为runnable不会产生值(将来将用null)。在特殊情况下,除了mainTasksFuture之外,它都会完成,但在成功情况下,它不会通过结果值。

如果第一个变体符合您的实际意图(调用者不应依赖于额外任务的完成),则只需将它们建模为依赖项:

mainTasksFuture.thenRunAsync(() -> {
    // extra tasks
});
return mainTasksFuture; // does not depend on the completion of extra task


否则,请使用变体2(减去过时的东西)

return mainTasksFuture.thenRunAsync(() -> {
  // extra tasks
}); // depends on the completion of extra task but results in (Void)null


如果您不需要结果值。否则,您可以使用

return mainTasksFuture.thenApplyAsync(response -> {
    // extra tasks
    return response;
}); // depends on the completion of extra task and returns original result


它与

return mainTasksFuture.thenCompose(response ->
    CompletableFuture.runAsync(() -> {
        // extra tasks
    }).thenApply(_void -> response));


不会忽略runAsync返回的未来,但与thenApplyAsync相比,这种并发症没有任何优势。

另一种选择是

return mainTasksFuture.whenComplete((response,failure) -> {
    if(failure == null) {
        // extra tasks
    }
});


因为whenComplete返回的未来将在原始任务的结果完成后完成。但是,即使原始的未来特别完成,也总是会评估该功能,因此如果不需要,则需要另一个条件。

关于java - `thenRunAsync(...)`和`CompletableFuture.runAsync(()-> {…}))是否完全相关?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57048331/

10-09 03:42