CompletableFuture how to return first FALSE or wait until all are completed to return TRUE

拈花ヽ惹草 提交于 2021-01-29 13:33:56

问题


I have a bit of an odd situation that doesn’t seem to allow this peg to fit into any of the widely established CompletableFuture holes.

  • Within a primary method that is evaluating returned booleans, I am wanting to allow calls to three different methods to complete asynchronously. Each of these three methods can return either a TRUE or a FALSE.
  • If any return a FALSE, I want the evaluation to drop the remainder and simply return that FALSE value. The point being, it can be any of the three, not necessarily the first.
  • But most importantly, I need the evaluation to wait until all three return TRUE before actually returning TRUE. This is critically important.

Right now, I am using a basic && chain to make this evaluation:

public boolean evaluateChecks() {
    return checkOne().Join() && checkTwo().Join() && checkThree().Join();
}

However this still does things in a specific order - if checkThree() is the first to return a FALSE value, it still has to wait until the prior two have provided their values before it gets evaluated, due to how the && fall-through works.

Right now all three methods return CompletableFuture<Boolean>, but I have no problem reverting these back into normal methods in order to run a CompletableFuture in the primary method that evaluates them.

I have looked at quite a few examples, but none seem to provide me with the functionality I need.


回答1:


Adapted from the answer by Didier L here:

  • How to implement CompletableFuture.allOf() that completes exceptionally once any of the futures fail?

Instead of using exceptionally and completeExceptionally, use thenAccept to complete the CompletableFuture returned by allOf().

For example, save the futures because you're about to chain actions on them:

CompletableFuture<Boolean> a = checkOne(), b = checkTwo(), c = checkThree();

Use CompletableFuture.allOf to wait for all of them to complete (presumably you're not expecting failures/exceptions) and transform the Void result into the expected Boolean value of true.

CompletableFuture<Boolean> allWithFailFast = CompletableFuture.allOf(a, b, c).thenApply(__ -> a.join() && b.join() && c.join());
// if there is an exception, it'll be propagated to the future returned by thenApply

With the returned CompletableFuture above, you can now complete it faster if any of the original futures completes with false.

Stream.of(a, b, c).forEach(f -> f.thenAccept(result -> {
    if (!result) {
        allWithFailFast.complete(false);
    }
}));

Depending on the order of completions and their result, either the allOf future will complete first with a result of evaluating the futures or one of the futures will return false and cause the allWithFailFast to complete with false.

If multiple futures complete with false, only the first call to

allWithFailFast.complete(false);

will do anything, the others will essentially be ignored.



来源:https://stackoverflow.com/questions/58999254/completablefuture-how-to-return-first-false-or-wait-until-all-are-completed-to-r

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!