CompletableFuture supplyAsync

Tua*_* Do 23 java concurrency java-8

我刚刚开始探索Java 8的一些并发功能.有一点让我困惑的是这两个静态方法:

CompletableFuture<Void> runAsync(Runnable runnable) 
CompletableFuture<U> supplyAsync(Supplier<U> supplier)
Run Code Online (Sandbox Code Playgroud)

有谁知道为什么他们选择使用界面供应商?使用Callable是不是更自然,这是Runnable的类比返回值?这是因为供应商不会抛出无法处理的异常吗?

Dim*_*rov 12

简短的回答

不,这不是更自然的使用Callable,而不是SupplierCompletableFuture.supplyAsync.这个论点几乎完全是关于语义的,所以如果你后来仍然觉得不相信也没关系.

答案很长

CallableSupplier功能接口/ SAM类型在功能几乎等同(原谅双关语),但它们的起源和预期用途而不同.

Callable是作为java.util.concurrent包的一部分创建的.这个包在Java 8中围绕lambda表达式的巨大变化之前出现,最初集中在一系列帮助你编写并发代码的工具上,而不会偏离经典的多线程经典模型.

主要目的Callable是抽象可以在不同线程中执行并返回结果的操作.来自Callable的Javadoc:

Callable接口类似于Runnable,在这两个被设计用于一个其实例潜在地由另一个线程执行.

Supplier是作为java.util.function包的一部分创建的.该包是Java 8中上述变化的组成部分.它提供了可由lambda表达式和方法引用作为目标的常见功能类型.

一种这样的类型是没有返回结果的参数的函数(即提供某种类型或Supplier函数的函数).

那么为什么SupplierCallable呢?

CompletableFuturejava.util.concurrent受到Java 8中上述变化启发的软件包添加的一部分,它允许开发人员以功能性,可隐式并行化的方式构造他的代码,而不是在其中显式处理并发.

它的supplyAsync方法需要一种方法来提供特定类型的结果,并且它对此结果更感兴趣,而不是为达到此结果而采取的操作.它也不一定关心特殊完成(另见下面的......段落).

仍然,如果Runnable用于无参数,无结果功能接口,不Callable应该用于无参数,单结果功能接口?

不必要.

未包含参数但未返回结果的函数的抽象(因此完全通过外部上下文的副作用操作)未包括在内java.util.function.这意味着(有点烦人)Runnable用于需要这种功能接口的地方.

Exception可以抛出的被检查怎么样Callable.call()

这是Callable和之间预期语义差异的一个小标志Supplier.

A Callable是一个可以在另一个线程中执行的动作,它允许您在执行时检查其副作用.如果一切顺利,您将获得特定类型的结果,但由于执行某些操作时会出现异常情况(特别是在多线程上下文中),您可能还需要定义和处理这种异常情况.

Supplier另一方面,A 是您依赖于提供某种类型对象的函数.特殊情况不应该成为您作为直接消费者的责任Supplier.这是因为:

  1. ...功能接口通常用于定义多阶段过程中的特定阶段以创建或变异数据,并且处理Exceptions可以是一个单独的阶段,以备您关心
  2. ...显式处理会Exception显着降低功能接口,lambda表达式和方法引用的表达能力