[英]Are `thenRunAsync(…)` and `CompletableFuture.runAsync(() -> { … });` related at all?
我需要执行一些额外的任务,但要让原始线程结束, 例如,发回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
内容实际上是在以不同的方式说出我所怀疑的内容。
runAsync
和thenRunAsync
执行异步的Runnable
taks
使用此阶段的默认异步执行工具执行给定操作
问题:换句话说,then * Async方法终止符(完成方法)是否在原始线程中返回前一个链的结果,然后生成一个新线程来执行其余操作?
答案:否,从文档中可以完成一个阶段,或者两个阶段都完成,或者两个阶段都可以触发一个阶段的执行 。因此,基本上可以根据程序员对该部分的编码方式来返回结果,但是现在情况下(使用thenRunAsync
),结果将在第一阶段完成后返回,因为在第二阶段thenRunAsync
您将第一阶段的结果作为输入,但不返回任何内容。
一个阶段的执行可以由一个阶段的完成或两个阶段的全部或两个阶段中的一个触发。 使用带有前缀的方法来安排对单个阶段的依赖。 通过两个阶段都完成而触发的结果可以使用相应命名的方法组合其结果或效果。 由两个阶段中的任何一个触发的结果不能保证哪个结果或效果用于从属阶段的计算。
第一个示例和第二个示例之间也存在细微差异
例如:1。在这个例子中Runnable
任务得到执行异步返回结果之前,这两个Function
从thenApply
和Runnable
从runAsync
将同时执行
return mainTasksFuture.thenApply(response -> {
CompletableFuture.runAsync(() -> {
// extra tasks
});
return response;
});
实施例:2在这个例子中Runnable
从任务thenRunAsync
将完成之后被执行Function
从thenApply
return mainTasksFuture.thenApply(response -> {
return response;
}).thenRunAsync(() -> {
// extra tasks
});
你写了
似乎只是纯粹基于方法名称,对于CompletableFutures的新手来说。
好吧,方法名称正确地反映了方法的作用。 runAsync
和thenRunAsync
启动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
返回的whenComplete
将以原始的whenComplete
结果完成。 但是,即使最初的未来异常完成,也始终会评估该函数,因此,如果不需要,则需要另一个条件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.