[英]Is there any difference between returning a void vs returning a CompletionStage<Void>?
更具体地说,有什么区别,在这两段代码中,一个返回void
,另一个返回CompletionStage<Void>
?
void
或CompletionStage<Void>
比另一个有什么优势?thenCompose
中的变量x
。 有没有更好的写法?doValidation
返回一个boolean
并在performTask
函数中检查是否为true
,这是一种更好的做法吗?代码示例 1:
public CompletionStage<Response> performTask(Request request) throws MyException {
doValidation(request);
return service.performTask(request).thenCompose(serviceResponse -> CompletableFuture.completedFuture(buildMyResponse(serviceResponse)));
}
private void doValidation(Request request) throws MyException {
CompletableFuture.runAsync(() -> {
// Validate
if (*someCondition*) {
throw new MyException(.....);
}
});
}
代码示例 2:
public CompletionStage<Response> performTask(Request request) throws MyException {
return doValidation(request).thenCompose(x -> {
return service.performTask(request).thenCompose(serviceResponse -> CompletableFuture.completedFuture(buildMyResponse(serviceResponse)));
});
}
private CompletionStage<Void> doValidation(Request request) throws MyException {
return CompletableFuture.runAsync(() -> {
// Validate
if (*someCondition*) {
throw new MyException(.....);
}
});
}
我正在回答你的第一个问题
What advantages of using one of void or CompletionStage<Void> over the other?
要了解差异,您应该尝试记录流。 它将帮助您确定它们的工作方式有何不同。
这是一个类似于您遵循的方法的示例。 我想出了我自己的例子,因为我不知道你的代码。
public class Test {
public static void main(String[] args) {
tryWithVoid();
// tryWithCompletionStageVoid();
}
public static void tryWithVoid() {
System.out.println("Started");
validate(null);
System.out.println("Exit");
}
public static void tryWithCompletionStageVoid() {
System.out.println("Started");
validateCS(null).thenRun(() -> System.out.println("Validation complete"));
System.out.println("Exit");
}
public static CompletionStage<Void> validateCS(String val) {
return CompletableFuture.runAsync(() -> {
if (val == null) {
System.out.println("Validation failed! value is null");
}
});
}
public static void validate(String val) {
CompletableFuture.runAsync(() -> {
if (val == null) {
System.out.println("Validation failed! value is null");
}
});
}
}
如果您运行tryWithVoid()
,您将看到输出将是:
Started
Exit
Validation failed! value is null
而当您运行tryWithCompletionStageVoid()
,它将是:
Started
Validation failed! value is null
Validation complete
Exit
在第一种方法tryWithVoid()
,它不会等待操作完成。 因此,操作的结果对于调用之后的代码可能可用,也可能不可用。
然而,在第二种方法tryWithCompletionStageVoid()
,它在运行下一个阶段之前等待阶段完成。
如果阶段之间没有依赖性,则可以使用void
不同之处在于,返回一个void
您无法执行任何链接到CompletableFuture
。
当您返回CompletableFuture<Void>
您可以将更多内容链接到它。 例如调用thenRun()
、 thenRunAsync()
或简单的join()
以等待它在需要时完成。
所以这取决于调用者是否关心CompletableFuture
的状态并希望应用附加到它的进一步逻辑。
在您的情况下,在示例 1 中, doValidation()
在单独的线程上运行,无论发生什么都无关紧要。 service.performTask()
将独立于它发生,甚至可以在doValidation()
之前开始和/或结束。
在示例 2 中, doValidation()
必须在performTask()
实际发生之前成功完成。 所以看起来这个版本实际上是正确的。 请记住,运行CompletionStage<Response> performTask()
的主线程将在设置管道后立即完成并返回,实际的 performValidation() 可能仍在运行(甚至可能尚未启动)。
顺便说一下,您可以按如下方式简化调用:
service.performTask(request).thenApply(this::buildMyResponse);
您不必再次将其包装在CompletableFuture
,只需使用thenCompose()
再次打开它thenCompose()
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.