问题描述
如果我有
CompletableFuture<Something> future1 = service.request(param1);
CompletableFuture<Something> future2 = service.request(param2);
CompletableFuture<Void> many = CompletableFuture.allOf(future1, future2);
当我做 many.cancel()$ c时会发生什么$ C>?
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 $ c相关联$ c>已经运行但尚未完成,取消
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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!