根据某些条件停止/完成循环的CompletableFuture [英] Stop/Complete a looped CompletableFuture based on some condition

查看:151
本文介绍了根据某些条件停止/完成循环的CompletableFuture的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

CompletableFuture<String> future = CompletableFuture.completedFuture(null);
for(int _retrial = 1 ; _retrial <= getRetrialCountBasedOnSomeLogic() ; _retrial++) {
  int finalRetrial = _retrial;
  future = future
      .thenCompose(lastRetrialStatus -> {
        if(Strings.isNullOrEmpty(lastRetrialStatus) || (!"SUCCESS".equals(lastRetrialStatus))) {
          return doSomeCalculations(finalRetrial);
        } else {
          return CompletableFuture.completedFuture(null);
        }
      })
      .handle((response, throwable) -> {
        if(throwable != null) {
          throwable = CompletableFutures.unwrapCompletionStateException(throwable);
          return throwable.getMessage();
        }
        return "SUCCESS";
      });
}
return future;

我最近开始在上面的代码中研究completablefutures-如您所见,我正在用for循环链接我的期货.如果句柄返回"SUCCESS",我希望链停止.像这样的东西:

I have recently started working on completablefutures, in the above code - As you can see I am chaining my futures with a for loop. I want the chain to stop if handle returns "SUCCESS". Something like this :

CompletableFuture<String> future = CompletableFuture.completedFuture(null);
for(int _retrial = 1 ; _retrial <= getRetrialCountBasedOnSomeLogic() ; _retrial++) {
  int finalRetrial = _retrial;
  future = future
      .thenCompose(lastRetrialStatus -> doSomeCalculations(finalRetrial))
      .handle((response, throwable) -> {
        if(throwable != null) {
          throwable = CompletableFutures.unwrapCompletionStateException(throwable);
          return throwable.getMessage();
        }
        **Its a success, I dont need to look for any further passes of this loop. Lets end here by returning "SUCCESS"**
      });
}
return future;

推荐答案

仅使重试操作链接成为处理程序的一部分,该处理程序仅在知道成功状态时才执行.由于通过lambda表达式定义的函数无法引用自身,因此您需要一种可以调用的方法,例如

Just make chaining a retry action a part of the handler that is only executed when the success state is known. Since a function defined via lambda expression can’t refer to itself, you need a method which you can call, e.g.

static CompletableFuture<String> yourMethod() {
    return yourMethod(1, getRetrialCountBasedOnSomeLogic());
}

private static CompletableFuture<String> yourMethod(int currentTry, int maxTries) {
    CompletableFuture<String> future = doSomeCalculations(currentTry);
    int nextTry = currentTry + 1;
    return future
        .handle((s, t) -> t == null? CompletableFuture.completedFuture("SUCCESS"):
            nextTry <= maxTries? yourMethod(nextTry, maxTries):
            CompletableFuture.completedFuture(
                CompletableFutures.unwrapCompletionStateException(t).getMessage()))
        .thenCompose(Function.identity());
}

不幸的是,没有 handle 映射到另一个未来的变体,因此我们需要先映射到一个未来的未来,然后是 .thenCompose(Function.identity())

Unfortunately, there is no variant of handle mapping to another future, so we need to map to a future of future followed by .thenCompose(Function.identity())

您可以通过有条件地链接不同的阶段来略微减少最后一次不需要合成的工作:

You could reduce the work slightly for the last attempt, which doesn’t need composition, by conditionally chaining different stages:

private static CompletableFuture<String> yourMethod(int currentTry, int maxTries) {
    CompletableFuture<String> future
        = doSomeCalculations(currentTry).thenApply(x -> "SUCCESS");
    int nextTry = currentTry + 1;
    return nextTry <= maxTries?
        future.thenApply(CompletableFuture::completedFuture)
            .exceptionally(t -> yourMethod(nextTry, maxTries))
            .thenCompose(Function.identity()):
        future.exceptionally(t ->
            CompletableFutures.unwrapCompletionStateException(t).getMessage());
}

如果 maxTries 不是常数,但需要像循环那样重新评估 getRetrialCountBasedOnSomeLogic(),则此变体也适用:

This variant also works if maxTries is not a constant but requires reevaluating getRetrialCountBasedOnSomeLogic(), as your loop does:

static CompletableFuture<String> yourMethod() {
    return yourMethod(1);
}

static CompletableFuture<String> yourMethod(int currentTry) {
    int maxTries = getRetrialCountBasedOnSomeLogic();
    CompletableFuture<String> future
        = doSomeCalculations(currentTry).thenApply(x -> "SUCCESS");
    int nextTry = currentTry + 1;
    return nextTry <= maxTries?
        future.thenApply(CompletableFuture::completedFuture)
            .exceptionally(t -> yourMethod(nextTry))
            .thenCompose(Function.identity()):
        future.exceptionally(t ->
            CompletableFutures.unwrapCompletionStateException(t).getMessage());
}

这篇关于根据某些条件停止/完成循环的CompletableFuture的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆