Java 是'thenRunAsync(…)'和'CompletableFuture.runAsync(()->;{…});'有关系吗?
我需要执行一些额外的任务,但让原始线程完成,例如,发回HTTP响应 我想我可以这样做:Java 是'thenRunAsync(…)'和'CompletableFuture.runAsync(()->;{…});'有关系吗?,java,multithreading,java-8,completable-future,Java,Multithreading,Java 8,Completable Future,我需要执行一些额外的任务,但让原始线程完成,例如,发回HTTP响应 我想我可以这样做: return mainTasksFuture.thenApply(response -> { CompletableFuture.runAsync(() -> { // extra tasks }); return response; }); 但我记得有一个然后是runasync。是 return mainTasksFuture.thenApply(response ->
return mainTasksFuture.thenApply(response -> {
CompletableFuture.runAsync(() -> {
// extra tasks
});
return response;
});
但我记得有一个然后是runasync
。是
return mainTasksFuture.thenApply(response -> {
return response;
}).thenRunAsync(() -> {
// extra tasks
});
基本上是做同样事情的另一种方式?换句话说,then*Async
方法是否是在原始线程中返回上一个链的结果,然后生成一个新线程来执行其余线程的终止符(完成方法)
我几乎可以肯定答案是否定的。对于一个刚刚接触CompletableFutures的人来说,这似乎仅仅是基于方法名。不过我想确认一下,以防我读到的关于ForkJoinPool.commonPool的内容实际上是以不同的方式表达了我的怀疑。运行异步和运行异步都执行
运行异步
使用此阶段的默认异步执行工具执行给定操作
问题:换句话说,then*异步方法终止符(完成方法)是否在原始线程中返回上一个链的结果,然后生成一个新线程来执行其余线程
回答:否,根据文档一个阶段的执行可能会由单个阶段、两个阶段或两个阶段中的任何一个阶段的完成触发。因此基本上,结果可能会根据程序员对该部分的编码方式返回,但现在在您的情况下(使用然后运行异步
)结果将在第一阶段完成后返回,因为在第二阶段thenRunAsync
中,您将第一阶段的结果作为输入,但不返回任何内容
一个阶段的执行可以通过完成单个阶段、两个阶段或两个阶段中的任何一个来触发。使用带有前缀then的方法排列对单个阶段的依赖关系。完成这两个阶段后触发的方法可以使用相应命名的方法将其结果或效果结合起来。由两个阶段中的任何一个触发的结果都不能保证哪一个结果或效果用于相关阶段的计算
第一个例子和第二个例子之间也有细微的区别
示例:1在本例中,Runnable
任务在返回结果之前异步执行,来自然后应用的函数
和来自runAsync
的Runnable
将同时执行
return mainTasksFuture.thenApply(response -> {
CompletableFuture.runAsync(() -> {
// extra tasks
});
return response;
});
示例:2在本例中,来自的Runnable
任务将在来自的功能完成后执行
return mainTasksFuture.thenApply(response -> {
return response;
}).thenRunAsync(() -> {
// extra tasks
});
你写的
只是∗似乎,对于刚接触CompletableFutures的人来说,这可能纯粹是基于方法名
好的,方法名称正确地反映了方法的功能。runAsync
和thenRunAsync
都会启动Runnable
的异步执行,并返回一个未来,该未来将在异步执行完成后完成。因此,名称的相似性是合理的
这是你的代码,这是根本不同的
在这个变体中
return mainTasksFuture.thenApply(response -> {
CompletableFuture.runAsync(() -> {
// extra tasks
});
return response;
});
您完全忽略了由runAsync
返回的未来,因此由thenApply
返回的未来将在触发异步操作后立即完成。调用方可以在“额外任务”仍在并发运行时检索结果值
相比之下
return mainTasksFuture.thenApply(response -> {
return response;
}).thenRunAsync(() -> {
// extra tasks
});
thenApply
完全过时了,因为它什么都不做。但是您返回的是由runasync
返回的未来,它将在Runnable
的异步执行完成并且类型为CompletableFuture
时完成,因为Runnable不会产生值(未来将以null
完成)。在例外情况下,它将在mainstassfuture
例外的情况下完成,但在成功的情况下,它不会传递结果值
如果第一个变量符合您的实际意图(调用者不应依赖于额外任务的完成),请不要将其建模为依赖项:
mainTasksFuture.thenRunAsync(() -> {
// extra tasks
});
return mainTasksFuture; // does not depend on the completion of extra task
否则,请使用变体2(减去过时的内容)
如果不需要结果值。否则,您可以使用
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
返回的未来将与原始未来的结果一起完成。但是函数总是被计算的,即使最初的将来异常地完成了,所以如果不需要,它需要另一个条件
return mainTasksFuture.whenComplete((response,failure) -> {
if(failure == null) {
// extra tasks
}
});