繁体   English   中英

返回 void 与返回 CompletionStage 之间有什么区别<Void> ?

[英]Is there any difference between returning a void vs returning a CompletionStage<Void>?

更具体地说,有什么区别,在这两段代码中,一个返回void ,另一个返回CompletionStage<Void>

  • 使用voidCompletionStage<Void>比另一个有什么优势?
  • 在 CODE SAMPLE 2 中,我没有使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM