gpt4 book ai didi

java - 在 Java 中嵌套 CompletionStages 以使内部 block 在外部 block 之前运行

转载 作者:行者123 更新时间:2023-12-02 10:41:39 24 4
gpt4 key购买 nike

我编写了如下方法:

 public static CompletionStage<Tuple2<ObjectNode, String>> calculateTemplateTreeAndKeys(
String content,
RequestContext context,
MetricsClient metricsClient,
JdbcSession jdbcSession) {

AtomicReference<ObjectNode> templateTreeHolder = new AtomicReference<>();
templateTreeHolder.set(Json.rootNode());

return getTemplateIds(context, metricsClient, jdbcSession, content)
.thenCompose(
templateIds -> {
templateIds.map(
id ->
// do something and return CompletionStage<String>
.thenAccept(
tree -> {
templateTreeHolder.set(
(ObjectNode)
templateTreeHolder.get().set(id, Json.readTree(tree)));

System.out.println(
"From inner function: " + templateTreeHolder.get());
}));
return CompletableFuture.completedFuture(NotUsed.getInstance());
})
.thenApply(
notUsed -> {
String includedTemplateIdsStr =
getKeysFromTemplateTree(templateTreeHolder.get()).toJavaList().toString();

System.out.println("From outer function: " + templateTreeHolder.get());

return Tuple.of(templateTreeHolder.get(), includedTemplateIdsStr);
});

我希望内部 block 先处理并更新 templateTreeHolder.thenApply 被调用,以便 templateTreeHolder 将保存正确的数据以返回。但是,.thenApply block 在内部 .thenAccept block 之前进行处理。

从控制台输出序列:

From outer function: {}
From inner function: {"f9406341-c62a-411a-9389-00a62bd63629":{}}

我不确定我在链接 CompletionStages 时做错了什么,请告诉我如何确保内部 block 在外部 block 之前完成?

最佳答案

您的函数传递给 thenCompose返回一个已经完整的 future ,即 return CompletableFuture.completedFuture(NotUsed.getInstance());这允许相关阶段立即进行。这似乎与传递给templateIds.map(…)的函数的求值相冲突。 ,这显然是异步发生的。

通常,您应该避免完成阶段和副作用依赖性的这种混合,特别是当它们的异步评估未建模为先决条件完成阶段时。

但是如果您别无选择,您可以解决此问题:

return getTemplateIds(context, metricsClient, jdbcSession, content)
.thenCompose(
templateIds -> {
// create an initially uncompleted stage
CompletableFuture<Object> subStage = new CompletableFuture<>();
templateIds.map(
id ->
// do something and return CompletionStage<String>
.thenAccept(
tree -> {
templateTreeHolder.set(
(ObjectNode)
templateTreeHolder.get().set(id, Json.readTree(tree)));

System.out.println(
"From inner function: " + templateTreeHolder.get());
// complete when all work has been done
subStage.complete(null);
}));
// use this stage for dependent actions
return subStage;
})
.thenApply(
notUsed -> {
String includedTemplateIdsStr =
getKeysFromTemplateTree(templateTreeHolder.get()).toJavaList().toString();

System.out.println("From outer function: " + templateTreeHolder.get());

return Tuple.of(templateTreeHolder.get(), includedTemplateIdsStr);
});

在上面的代码中,如果您的操作在尝试完成之前因异常而失败,则 future 将永远不会完成。一般模式如下:

CompletableFuture<Type> stage = new CompletableFuture<>();

try {
code that will eventually call complete on stage
}
catch(Throwable t) {
stage.completeExceptionally(t);
}

但是,当然,当应该完成该阶段的代码也承担异步处理时,情况会变得更加复杂,因此您必须保护尝试提交实际完成代码的代码以及实际完成代码.

因此,内部代码的更详细版本将如下所示:

CompletableFuture<Object> subStage = new CompletableFuture<>();
try {
templateIds.map(
id ->
// do something and return CompletionStage<String>
.thenAccept(
tree -> {
templateTreeHolder.set(
(ObjectNode)
templateTreeHolder.get().set(id, Json.readTree(tree)));

System.out.println(
"From inner function: " + templateTreeHolder.get());
})
.whenComplete((v,t) -> {
// complete when all work has been done
if(t != null) subStage.completeExceptionally(t);
else subStage.complete(v);
}));
} catch(Throwable t) {
subStage.completeExceptionally(t);
}
// use this stage for dependent actions
return subStage;

(也许,“做某事并返回 CompletionStage”也必须用 try { … } catch(Throwable t) { subStage.completeExceptionally(t); } 来保护)

关于java - 在 Java 中嵌套 CompletionStages 以使内部 block 在外部 block 之前运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52887027/

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