简体   繁体   中英

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

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.

Adapted from the answer by Didier L here:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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