简体   繁体   English

Java短路CompletableFuture

[英]Java short circuit CompletableFuture

I am trying to find a way to skip CompletableFuture based on specific conditions. 我试图找到一种基于特定条件跳过CompletableFuture的方法。

For example 例如

public CompletableFuture<Void> delete(Long id) {
    CompletableFuture<T> preFetchCf = get(id);
    CompletableFuture<Boolean> cf1 = execute();

    /*This is where I want different execution path, if result of this future is true go further, else do not*/

    // Execute this only if result of cf1 is true
    CompletableFuture<T> deleteCf = _delete(id);
    // Execute this only if result of cf1 is true
    CompletableFuture<T> postDeleteProcess = postDelete(id);
}

What is a good way to achieve this ? 什么是实现此目标的好方法?

I will prepare a different example than the one you used in the question, because your code is not quite clear in intent from the readers perspective. 我将准备一个与您在问题中使用的示例不同的示例,因为从读者的角度来看,您的代码意图并不十分清楚。

First suppose the existing of a CompletableFuture<String> that provides the name of a Star Wars characters. 首先假设存在一个提供了《星球大战》角色名称的CompletableFuture<String>

CompletableFuture<String> character = CompletableFuture.completedFuture("Luke");

Now, imagine I have two other CompletableFuture that represent different paths I may want to follow depending on whether the first completable future provides a character that is a Jedi. 现在,假设我还有另外两个CompletableFuture ,它们表示我可能要遵循的路径,这取决于第一个可完成的未来是否提供了绝地角色。

Supplier<CompletableFuture<String>> thunk1 = () -> CompletableFuture.completedFuture("This guy is a Jedi");
Supplier<CompletableFuture<String>> thunk2 = () -> CompletableFuture.completedFuture("This guy is not a Jedi");

Notice that I wrapped the CompletableFuture in aa Supplier , to avoid that they get eagerly evaluated (this is concept known as thunk ). 请注意,我将CompletableFuture包装在a Supplier ,以避免对其进行热切评估(这被称为thunk )。

Now, I go and to my asynchronous chain: 现在,我转到我的异步链:

character.thenApply(c -> isJedi(c))
            .thenCompose(isJedi -> isJedi ? thunk1.get() : thunk2.get())
            .whenComplete((answer, error) -> System.out.println(answer));

The use of thenCompose let me choose a path based on the boolean result. 然后使用thenCompose让我根据布尔结果选择路径。 There I evaluate one of the thunks and cause it to create a new CompletableFuture for the path I care about. 在这里,我评估了一个重击,并使其针对我所关心的路径创建了一个新的CompletableFuture

This will print to the screen "This guys is a Jedi" . 这将打印到屏幕"This guys is a Jedi"

So, I believe what you're looking for is the thenCompose method. 因此,我相信您正在寻找的是thenCompose方法。

Not sure if I understand your objective, but why won't you just go with future chaining like you said in the comment? 不知道我是否理解您的目标,但是为什么不按照评论中的意见继续进行未来的链接呢? Something like this, just to illustrate: 这样的东西,只是为了说明:

public class AppTest {
    @Test
    public void testCompletableFutures() {
        Integer id = (int) Math.random() * 1000;

        CompletableFuture<Void> testing = AppTest.execute()
                .thenAcceptAsync(result -> {
                    System.out.println("Result is: " + result);
                    if(result)
                        AppTest.delete(id);
                    else
                        throw new RuntimeException("Execution failed");
                })
                .thenApplyAsync(result -> AppTest.postDelete())
                .thenAcceptAsync(postDeleteResult -> {
                    if(postDeleteResult)
                        System.out.println("Post delete cleanup success");
                    else
                        throw new RuntimeException("Post delete failed");
                });
    }

    private static boolean postDelete() {
        System.out.println("Post delete cleanup");
        return Math.random() > 0.3;
    }

    private static CompletableFuture<Boolean> delete(int i) {
        System.out.println("Deleting id = " + i);
        return CompletableFuture.completedFuture(true);
    }

    private static CompletableFuture<Boolean> execute() {
        return CompletableFuture.supplyAsync(() -> Math.random() > 0.5);
    }
}

Of course that doesn't make much real-life sense, but I think it works to show a concept. 当然,这在现实生活中意义不大,但我认为它可以显示一个概念。

If you want to skip the second call after execute based on the result it's clearly not possible since you need that result. 如果要根据结果在execute后跳过第二个调用,则显然不可能,因为您需要该结果。 The point is that it should not matter for you whether you skipped that or not since it's asynchronous, you are not blocking to wait for that result. 关键是,因为它是异步的,所以是否跳过对您来说都没有关系,您不会阻塞等待该结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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