当前位置: 首页 > 知识库问答 >
问题:

whenComplete()如何在CompletionStages链中工作?

东郭腾
2023-03-14

我以为我理解了,但我现在不确定。这个问题源于另一条线索。

在我的公司,我们处理期货的方式是将它们链接起来:

CompletionStage<Foo> getFoo() {
  // ...
  return barService.getBar()
      .thenCompose(bar -> {
        CompletionStage<Baz> baz = bazService.getBaz(bar);
        // ...
        return qux;
      })
      .thenApply(qux -> {
        CompletionStage<Quux> quux = quuxService.getQuux(qux);
        // ...
        return foo;
      });
}

qux和qux显然是foo、bar和baz之后的元语法变量

现在,假设我想在收到foo后发送一封确认电子邮件。我不需要发送这封确认邮件来阻止对任何被称为getFoo的客户端的响应。对于这些场景,我们在完成时使用:

CompletionStage<Foo> getFoo() {
  // ...
  return barService.getBar()
      .thenCompose(bar -> {
        CompletionStage<Baz> baz = bazService.getBaz(bar);
        // ...
        return qux;
      })
      .thenApply(qux -> {
        CompletionStage<Quux> quux = quuxService.getQuux(qux);
        // ...
        return foo;
      })                                     _
      .whenComplete((foo, ex) -> {.           |
          if (ex == null) {                   |
            emailService.sendEmail(foo);      | (NEW)
          }                                   |
      });                                    _|
}

现在我认为当完成时的动作发生在一个独立的线程中,完全独立于它起源的线程。换句话说,我认为只要找到foo,它就会被发送到调用方,无论在完成时内部发生了什么。但在现实中,当电子邮件服务出现问题并引发异常时,异常会一直向上传播,即即使成功找到了getFoo,也会引发异常。

我被指向Javadoc for whincomplete,它确实说:

与方法句柄不同,此方法不是为转换完成结果而设计的,因此提供的操作不应引发异常。但是,如果确实如此,则适用以下规则:如果此阶段正常完成,但提供的操作引发异常,则返回的阶段异常完成,提供的操作出现异常。或者,如果此阶段异常完成,并且提供的操作引发异常,那么返回的阶段将异常完成,并出现此阶段的异常。

这就是我困惑的地方:

我认为当完成时的全部目的是允许原始线程继续前进,而无需等待when完成中的操作。如果链是否会正常完成取决于when完成动作,这不是意味着链总是必须等待when完成如何完成吗?如果是真的,when完成有什么帮助?

我肯定我在想一些错误/误解未来是如何运作的,但我不知道是什么。

共有1个答案

轩辕庆
2023-03-14

<代码>。whenComplete类似于finally块。当你想做某事时,即使前一个阶段失败了,它也很有用。例如,在不停止故障传播的情况下记录异常或清理某些资源。

在您的情况下,您似乎只想在没有失败的情况下发送电子邮件。您可以将其重写为:

.thenAccept(emailService::sendEmail);

在这种情况下,如果发送电子邮件返回void,。方法完成后,将返回Accept。但是如果sendmail返回一个CompletionStage

如果您想控制线程执行器,可以使用。然后是*异步方法,而不是常规方法。否则,管道将在同一个线程中运行所有内容(如果可能,情况并非总是如此)。

 类似资料:
  • 我是编程新手,正在使用Python学习更复杂的数据结构,我发现很难理解使用头和尾向链表添加元素的概念。 关键是当我添加第一个元素时,一切都清楚了。由于head一开始是None,它将向tail和head添加新节点。当我添加第二个元素时,问题就开始了:我不明白为什么第二个元素会与当这行代码self时_尾执行next=newNode。在这行代码之后,成为第二个元素,这似乎很符合逻辑,因为我必须在不断添加

  • 区块链是以数字方式存储数据的概念。这些数据以块为单位。这些块链接在一起并使数据不可变。当数据块与其他块链接时,其数据永远不会再次更改。它可以公开提供给任何想要再次看到它的人,它以添加到区块链的那个序列显示。没有人可以在区块链上更改该信息。 在上一节中,我们已经学习了如何构建块以及加密哈希如何与整个过程相关联。在这里,您将学习区块链如何将所有这些概念结合使用,以保持完整区块链的完整性。 想象一下如下

  • 问题内容: 我正在分析存储过程中的一些旧SQL代码。 等等… 等等… 所以我想知道当它们都在同一个select语句中时,这些赋值如何工作。我假设在调用select之后,Var2 = OldValue,但是我想确定。 围绕这种情况有哪些规则?分配是否按照声明的顺序执行?如果是这样,在以下情况下将为Var2分配什么值: 谢谢! 问题答案: 退货 因此,在这种情况下,它们以从左到右的顺序执行, 但这 不

  • 问题内容: 我不是在问什么合适的链接语法,我知道它可能是这样的: 但是,我真的很想了解它的内部工作,据我所知,链接是与其他著名框架相比的优势之一,但是对于像我这样的新手程序员来说,这是很多抽象的东西,我敢肯定在那里可以提供一个解释,让我了解链接的工作方式。 谢谢! 问题答案: 如果您的对象具有某些方法,并且每个方法都返回带有方法的对象,则只需从返回的对象中调用一个方法。

  • 问题内容: 我想知道Java链接器如何工作。具体来说,它将类,接口,包,方法等以何种顺序组合为jvm可执行格式。我在这里找到了一些信息,但是关于链接顺序的信息并不多。 问题答案: 没有Java“链接器”之类的东西。但是,存在类加载器的概念,该类加载器给出了“某处”中的java字节代码数组,可以创建类的内部表示形式,然后可以与etc 一起使用。 在这种情况下,接口只是特殊的类。加载类后,方法和字段将

  • 问题内容: 我试图让我直接想到执行jQuery样式函数链接的原理。我的意思是: 我有一个例子可以工作,而另一个则没有。我将在下面发布。我一直想学习某种事物如何工作的第一原理基础知识,以便我可以在此基础上进行构建。到现在为止,我对链接的工作方式只有一个粗略而松散的理解,并且遇到了无法智能解决问题的错误。 我知道的: 函数必须返回自己,也就是“返回此”; 可链接函数必须驻留在jQuery的父函数中。a