本文介绍了递归取消allOff CompletableFuture的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有

CompletableFuture<Something> future1 = service.request(param1);
CompletableFuture<Something> future2 = service.request(param2);
CompletableFuture<Void> many = CompletableFuture.allOf(future1, future2);

当我做 many.cancel() future1 future2 也会被取消吗?如果没有,那么实现这一目标的最简洁方法是什么?我不愿意继续 future1 future2 ,只是为了能够在我想要取消时取消它们很多

what will happen when I do many.cancel()? Will future1 and future2 be cancelled as well? If not, what would be the cleanest way to achieve this? I'm reluctant to hold on to future1 and future2, just to be able to cancel them when I want to cancel many.

我想要这个的一些背景:收到一条数据时,我需要请求匹配,可能是将来执行计算的数据。如果有更新的数据到达,我想取消先前计算的完成,因为结果将立即被新计算取代。

Some background on why I want this: when receiving a piece of data, I need to request matching, potentially future data to perform a computation. If a newer piece of data arrives, I want to cancel the completion of the earlier computation, because the result will immediately be superceded by the new computation.

推荐答案

在你让生活变得艰难之前,你应该知道取消 CompletableFuture 实际上是什么。最重要的是,它停止相关计算。

Before you make you life harder than necessary, you should become aware of what cancelling a CompletableFuture actually does. Most important, it does not stop the associated computation.

如果计算与 CompletableFuture 已经运行但尚未完成,取消 CompletableFuture 将其变为已取消状态,这可能对所有相关阶段产生直接影响,但不是计算,它将一直持续到完成,但它试图完成取消的未来不会有任何影响。

If a computation associated with a CompletableFuture is already running, but has not completed yet, cancelling a CompletableFuture turns it into the "cancelled" state, which may have an immediate effect on all dependent stages, but not on the computation, which will continue until complete, though its attempt to complete the cancelled future will not have any effect.

而其他 Future 可能会被中断取消,这将停止计算,如果它检查中断,这不适用于 CompletableFuture ,请参阅:

While other Future’s might be cancelled with interruption, which will stop the computation, if it checks for interruption, this doesn’t apply to CompletableFuture, see CompletableFuture.cancel(boolean):

所以当你取消时, future1 future2 ,成功,唯一的直接影响是取消很多,你也可以通过在许多本身上调用 cancel 来实现。如果有更多的依赖阶段会产生更广泛的影响,但是既然你说过,你不想继续引用 future1 future2 ,似乎不是这样。

So when you cancel either, future1 or future2, successfully, the only immediate effect would be the cancellation of many, which you can also achieve by calling cancel on many itself. It would have a broader effect, if there were more dependent stages, but since you stated, that you don’t want to keep references to future1 or future2, this doesn’t seem to be the case.

以下代码演示了这种行为:

The following code demonstrates the behavior:

CompletableFuture<String> supply = CompletableFuture.supplyAsync(() -> {
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2));
    System.out.println("supplying value");
    return "foo";
});
CompletableFuture<String> then = supply.thenApply(s -> {
    System.out.println("Evaluating next stage");
    return s;
});
CompletableFuture<?> last = then.handle((s,t) -> {
    System.out.println("last stage: value: "+s+", throwable: "+t);
    return "";
});
System.out.println("cancelling: "+supply.cancel(true));
ForkJoinPool.commonPool().awaitQuiescence(1, TimeUnit.DAYS);

此代码可重复打印:

last stage: value: null, throwable: java.util.concurrent.CompletionException: java.util.concurrent.CancellationException
canceling: true
supplying value

(订单可能会改变)

无论你是否致电 supply.cancel(true) then.cancel(true)或是否通过 true false ;它不会停止正在进行的供应商评估。

regardless of whether you call supply.cancel(true) or then.cancel(true) or whether you pass true or false; it won’t stop the ongoing Supplier evaluation.

如果相关计算没有,那将会有所不同尚未启动,它确实在启动时检查取消状态,就像 CompletableFuture 中的便捷方法所产生的操作一样。这是一种罕见的情况,通常,您的 service.request(paramN)调用应该触发评估。

There will be a difference, if the associated computation hasn’t been started yet and it does check the cancellation state when starting, like with the actions produced by the convenience methods in CompletableFuture. This is a rare situation, as normally, your service.request(paramN) call is supposed to trigger the evaluation.

它是 CompletableFuture 的基本属性,顾名思义,它是可完成的,即任何人都可以调用完成,因此, CompletableFuture 无法控制最终可能调用完成的人在未来。所有, cancel 可以实现,是将其设置为已取消状态,这意味着忽略后续完成尝试并将取消向下传播到依赖操作。

It’s a fundamental property of the CompletableFuture, as its name suggests, that it is completable, i.e. anyone could call complete on it, thus, the CompletableFuture can’t control whoever might eventually call complete on it in the future. So all, cancel can achieve, is to set it to the cancelled state, which implies ignoring subsequent completion attempts and propagating the cancellation downward to the dependent actions.

所以底线是你可能已经没事了,只需要打电话给取消 许多实例,因为在 future1 上调用取消并且 future2 不太可能产生值得代码复杂化的效果。

So the bottom line is that you might already be fine with just calling cancel on the many instance, because calling cancel on future1 and future2 is unlikely to have an effect that is worth the complication of your code.

这篇关于递归取消allOff CompletableFuture的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-11 21:54