CompletableFuture的完成处理程序在哪个线程中执行?

我对CompletableFuture方法有疑问:

public <U> CompletableFuture<U> thenApply(Function<? super T, ? extends U> fn)

事情是JavaDoc这么说的:

返回一个新的CompletionStage,当此阶段正常完成时,将使用该阶段的结果作为所提供函数的参数来执行该阶段。有关涵盖异常完成的规则​​,请参见CompletionStage文档。

那线程呢?这将在哪个线程中执行?如果将来由线程池完成怎么办?

回答:

CompletableFuture文档中指定的策略可以帮助您更好地理解:

  • 对于非异步方法依赖完井供给动作可以由执行 该完成当前CompletableFuture线程或者通过完成方法的任何其他呼叫者

  • 所有没有显式Executor参数的异步方法都使用来执行ForkJoinPool.commonPool()(除非它不支持

    并行度至少为2,在这种情况下,将创建一个新的Thread来运行每个任务

    )。为了简化监视,调试和跟踪,所有生成的异步任务都是标记接口的实例CompletableFuture.AsynchronousCompletionTask

:我也建议阅读@Mike的答案,作为对文档详细信息的有趣分析。

正如@nullpointer指出的那样,文档会告诉您您需要了解的内容。但是,相关文本令人惊讶地模糊不清,此处发布的某些评论(和答案)似乎依赖于文档不支持的假设。因此,我认为有必要将其分开。具体来说,我们应该非常仔细地阅读本段内容:

为非异步方法的相关完成提供的动作可以由完成当前CompletableFuture的线程执行,也可以由完成方法的任何其他调用者执行。

听起来很简单,但是细节上却很少。似乎故意避免描述何时可以在完成线程上调用依赖完成,而不是在调用诸如的完成方法期间thenApply。如前所述,以上段落实际上是在恳求我们用假设来填补空白。这很危险,特别是当主题涉及并发和异步编程时,当我们随着程序员的发展而产生的许多期望被抛诸脑后。让我们仔细看一下文档中没有说的内容。

该文档没有声称在调用之前注册的相关完成complete()将在完成线程上运行。而且,尽管它声明在调用诸如的完成方法时可能会调用从属补全thenApply,但并未声明将在注册它的线程上调用补全(注意单词“ any other”)。

对于任何CompletableFuture用于计划和撰写任务的人来说,这些都是潜在的重要点。考虑以下事件序列:

  1. 线程A通过注册一个相关的完成f.thenApply(c1)
  2. 一段时间后,线程B调用f.complete()
  3. 大约在同一时间,线程C通过注册另一个依赖完成f.thenApply(c2)

从概念上讲,complete()它做两件事:发布将来的结果,然后尝试调用相关的完成。现在,如果线程C 在发布结果值之后但在线程B开始调用之前运行,该c1怎么办?根据实现的不同,线程C可能会看到f已经完成,然后可以调用c1 和 c2。或者,线程C可以调用,c2而线程B可以调用c1。该文档不排除任何可能性。考虑到这一点,以下是文档不支持的假设:

  1. 在调用之前将调用在完成之前c注册的从属完成。f f.complete()
  2. c到时间f.complete()回来,那将完成;
  3. 依赖完成将以任何特定顺序(例如注册顺序)被调用;
  4. 完成之前 注册的相关完成f将在完成之后 注册的f完成之前调用。

考虑另一个示例:

  1. 线程A调用f.complete();
  2. 一段时间后,线程B通过f.thenApply(c1); 注册完成。
  3. 大约在同一时间,线程C通过分别注册一个完成f.thenApply(c2)

如果知道f已经完成,可以尝试假设c1会在期间调用f.thenApply(c1)和c2会在期间调用f.thenApply(c2)。人们可能会进一步假设,c1到时间f.thenApply(c1)返回时,它已经完成了。但是,文档不支持这些假设。它可能是一个线程,呼吁thenApply各上调调用既 c1和c2,而其他线程调用都不是。

仔细分析JDK代码可以确定上面的假设方案如何发挥作用。但这甚至是有风险的,因为您最终可能会依赖于(1)不可移植或(2)可能会更改的实现细节。最好的选择是不要假设javadocs或原始JSR规范中未阐明的任何内容。

tldr:谨慎假设,编写文档时,请尽可能清晰明了。简洁是一件奇妙的事情,但请注意人类填补空白的趋势。

以上是 CompletableFuture的完成处理程序在哪个线程中执行? 的全部内容, 来源链接: utcz.com/qa/414593.html

回到顶部