首页 > 解决方案 > 链 CompletableFuture 并在第一次成功时停止

问题描述

我正在使用一个返回CompletableFutures 来查询设备的 API(类似于digitalpetri modbus)。

我需要用几个选项调用这个 API 来查询设备并弄清楚它是什么——这基本上是反复试验,直到它成功。这些是我无法更改的嵌入式设备协议,但您可以认为该过程类似于以下内容:

  1. 你是苹果吗?
  2. 如果不是,那你是菠萝吗?
  3. 如果不是,那你是钢笔吗?
  4. ...

虽然 API 使用期货,但实际上,通信是串行的(通过同一条物理线路),因此它们永远不会同步执行。一旦我知道它是什么,我希望能够停止尝试并让调用者知道它是什么。

我已经知道我只能得到一个期货的结果any(见下文),但这可能会导致应该避免的额外尝试。

有没有一种模式来链接期货,一旦其中一个成功就停止?

类似,但浪费了非常有限的资源。

List<CompletableFuture<String>> futures = Arrays.asList(
    CompletableFuture.supplyAsync(() -> "attempt 1"),
    CompletableFuture.supplyAsync(() -> "attempt 2"),
    CompletableFuture.supplyAsync(() -> "attempt 3"));

CompletableFuture<String>[] futuresArray = (CompletableFuture<String>[]) futures.toArray();
CompletableFuture<Object> c = CompletableFuture.anyOf(futuresArray);

标签: javajava-8completable-future

解决方案


我认为你能做的最好的事情是,在你检索到结果之后,

futures.forEach(f -> f.cancel(true));

这不会影响产生结果的一方,并尽力阻止其他一方。由于 IIUC 是从外部来源获得的,因此不能保证它实际上会中断他们的工作。

然而,由于

此类无法直接控制导致其完成的计算,取消被视为另一种形式的异常完成

(来自CompletableFuture文档),我怀疑它会做你真正想要的。


推荐阅读