我有一个关于CompletableFuture方法的问题:
public <U> CompletableFuture<U> thenApply(Function<? super T, ? extends U> fn)
JavaDoc的意思是:
返回一个新的完成阶段,当此阶段正常完成时,将使用此阶段的结果作为所提供函数的参数来执行该阶段。有关异常完成的规则,请参阅完成阶段文档。
穿线呢?这将在哪个线程中执行?如果未来由线程池来完成呢?
在Javadoc中:
为非异步方法的相关完成提供的操作可以由完成当前CompletableFuture的线程执行,或者由完成方法的任何其他调用方执行。
更具体地说:
>
fn
将在调用完成()
的线程的上下文中运行。
如果完成()
在调用Apply()
时已经完成,则fn
将在调用然后Apply()
的线程上下文中运行。
“可完成的未来
”文档中指定的策略可以帮助您更好地理解:
> < li>
为非异步方法的相关完成提供的操作可以由完成当前CompletableFuture的线程执行,或者由完成方法的任何其他调用方执行。
所有没有显式执行器参数的异步方法都使用 ForkJoinPool.commonPool()
执行(除非它不支持至少两个的并行级别,在这种情况下,将创建一个新的线程来运行每个任务)。为了简化监视、调试和跟踪,所有生成的异步任务都是标记接口“可完成”
的实例。
更新:我还建议通过@Mike来阅读这个答案,作为对文档细节的进一步有趣分析。
正如@nullpoer所指出的,留档会告诉你你需要知道的。然而,相关文本出奇地模糊,这里发布的一些评论(和答案)似乎依赖于留档不支持的假设。因此,我认为值得把它拆开。具体来说,我们应该非常仔细地阅读这一段:
为非异步方法的相关完成提供的操作可以由完成当前CompletableFuture的线程执行,或者由完成方法的任何其他调用方执行。
听起来很简单,但细节很简单。它似乎有意避免描述何时可以在完成线程上调用依赖完成,而不是在调用完成方法(如然后Apply
)期间调用依赖完成。如上所述,上述段落实际上要求我们用假设来填补空白。这是很危险的,尤其是当主题涉及并发和异步编程时,我们作为程序员的许多期望都被推翻了。让我们仔细看看文档中没有说什么。
该留档不声明在调用完成()
之前注册的依赖完成将在完成线程上运行。此外,虽然它声明在调用像thenApply
这样的完成方法时可能会调用依赖完成,但它没有声明将在注册它的线程上调用完成(注意单词“任何其他”)。
对于任何使用< code>CompletableFuture来计划和编写任务的人来说,这些都是潜在的要点。考虑这一系列事件:
f.thenApply(c1)
注册依赖完成f.complete()
f.thenApply(c2)
注册另一个依赖完成从概念上讲,< code>complete()做两件事:它发布未来的结果,然后它尝试调用相关的完成。现在,如果线程C在结果值被提交之后,但在线程B开始调用< code>c1之前运行,会发生什么呢?根据实现的不同,线程C可能会看到< code>f已经完成,然后它可能会调用< code>c1和< code>c2。或者,线程C可以调用< code>c2,而让线程B调用< code>c1。文件没有排除任何一种可能性。记住这一点,以下是文档不支持的假设:
f
上注册的从属完成 c
将在调用 f.complete()期间
被调用;c
将在 f.complete()
返回时运行到完成;f
完成之前注册的依赖完成将在 f
完成后注册的完成之前调用。考虑另一个例子:
f。complete()
f注册完成。然后应用(c1)
f.thenApply(c2)
注册一个单独的完成如果已知f
已经运行完毕,人们可能会认为c1
将在
,
c2执行期间调用。可以进一步假设
c1
将在f之前运行完成。然后Apply(c1)
返回。然而,文件并不支持这些假设。其中一个线程调用,然后Apply
最终可能同时调用了c1
c2
仔细分析 JDK 代码可以确定上述假设场景可能如何发挥作用。但即使这样也是有风险的,因为您最终可能依赖于(1)不可移植或(2)可能发生变化的实现细节。你最好的选择是不要假设任何在javadocs或原始JSR规范中没有拼写出来的东西。
tldr:小心你的假设,当你写文档时,要尽可能清晰和深思熟虑。虽然简洁是一件美妙的事情,但要警惕人类填补空白的倾向。
问题内容: 我对CompletableFuture方法有疑问: 事情是JavaDoc这么说的: 返回一个新的CompletionStage,当此阶段正常完成时,将使用该阶段的结果作为所提供函数的参数来执行该阶段。有关涵盖异常完成的规则,请参见CompletionStage文档。 那线程呢?这将在哪个线程中执行?如果将来由线程池完成怎么办? 问题答案: 文档中指定的策略可以帮助您更好地理解: 对
我有一个关于CompletableFuture方法的问题: 问题是JavaDoc只说了这么一句话: 返回一个新的CompletionStage,当此阶段正常完成时,将以此阶段的结果作为所提供函数的参数执行该CompletionStage。有关例外完成的规则,请参阅CompletionStage文档。 穿线呢?这将在哪个线程中执行?如果未来是由一个线程池来完成的呢?
我正在尝试在我的Swift应用程序中创建一个服务对象,以便更轻松地处理请求。我已经把它连接起来了,但是我可能误解了完成处理器。 我有这个函数,它只是发布到我正在运行的本地APIendpoint。 我需要做的就是把这个名字传给我在这里做的函数 但是,我现在收到此错误。 调用中缺少参数“completion”的参数 我的目标是返回< code>Response对象,这样我就可以访问它的属性,在UI中做
我的完成处理程序有问题。下面是一个带有完成处理程序的函数,位于一个实用程序文件中: 我在视图控制器中调用它 输出清楚地表明该函数在运行该块之前没有等待完成: 我如何解决这个问题?
我要做的是异步计算树结构的深度,我将有树的第一层,我想启动一个异步线程来分别计算每个节点的深度。 在计算过程中,树中显然可能有一个分叉,在这一点上,我想踢一个额外的线程来计算那个分支。 我已经得到了这个工作,但我需要做一些整理逻辑,当所有这些未来完成。但我对这一过程中产生的额外的可完成的未来感到困扰。 我会用什么方法来保存所有开始的CompletableFutures+那些动态创建的,并且在执行任
我目前正在学习swift,几个小时以来我一直在试图理解一个错误。由于查询,我试图从php脚本中获取一个xml文件,我使用一个完成处理程序作为回调来获取这些查询的结果。 问题是我对这些技术感到不舒服,它说缺少论据。 下面是使用完成处理程序的函数: 这是我调用这个函数的一段代码: 这段代码显示有关调用连接的此错误: 我做错了什么?为什么它要两个参数? 非常感谢您的帮助。 埃尔巴托