gpt4 book ai didi

java - Chain CompletableFuture 并在第一次成功时停止

转载 作者:行者123 更新时间:2023-11-30 02:09:31 24 4
gpt4 key购买 nike

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

我需要使用几个选项来调用此 API 来查询设备并找出它是什么 - 这基本上是反复试验,直到成功。这些是我无法更改的嵌入式设备协议(protocol),但您可以将该过程视为类似于以下内容的工作方式:

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

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

我已经知道我只能使用 any 获得其中一个 future 的结果(见下文),但这可能会导致应避免的额外尝试。

是否存在一种链接 future 的模式,一旦其中一个成功,您就停止?

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

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);

最佳答案

假设您有一个如您所描述的“伪异步”方法,即它有一个异步 API,但需要一些锁定才能执行:

private final static Object lock = new Object();

private static CompletableFuture<Boolean> pseudoAsyncCall(int input) {
return CompletableFuture.supplyAsync(() -> {
synchronized (lock) {
System.out.println("Executing for " + input);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return input > 3;
}
});
}

还有一个List<Integer>您想要根据此方法检查的输入的数量,您可以使用递归组合按顺序检查每个输入:

public static CompletableFuture<Integer> findMatch(List<Integer> inputs) {
return findMatch(inputs, 0);
}

private static CompletableFuture<Integer> findMatch(List<Integer> inputs, int startIndex) {
if (startIndex >= inputs.size()) {
// no match found -- an exception could be thrown here if preferred
return CompletableFuture.completedFuture(null);
}
return pseudoAsyncCall(inputs.get(startIndex))
.thenCompose(result -> {
if (result) {
return CompletableFuture.completedFuture(inputs.get(startIndex));
} else {
return findMatch(inputs, startIndex + 1);
}
});
}

这将像这样使用:

public static void main(String[] args) {
List<Integer> inputs = Arrays.asList(0, 1, 2, 3, 4, 5);
CompletableFuture<Integer> matching = findMatch(inputs);

System.out.println("Found match: " + matching.join());
}

输出:

Executing for 0
Executing for 1
Executing for 2
Executing for 3
Executing for 4
Found match: 4

如您所见,没有调用它来输入 5 ,而您的 API ( findMatch() ) 保持异步。

关于java - Chain CompletableFuture 并在第一次成功时停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50517771/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com