我刚刚开始研究Java8的一些并发特性。有一件事让我有点困惑,那就是这两种静态方法:
CompletableFuture<Void> runAsync(Runnable runnable)
CompletableFuture<U> supplyAsync(Supplier<U> supplier)
有人知道他们为什么选择使用接口供应商吗?使用callable不是更自然吗?callable类似于runnable,返回一个值?这是因为供应商没有抛出无法处理的异常吗?
我刚刚开始研究Java8的一些并发特性。有一件事让我有点困惑,那就是这两种静态方法:
CompletableFuture<Void> runAsync(Runnable runnable)
CompletableFuture<U> supplyAsync(Supplier<U> supplier)
有人知道他们为什么选择使用接口供应商吗?使用callable不是更自然吗?callable类似于runnable,返回一个值?这是因为供应商没有抛出无法处理的异常吗?
1条答案
按热度按时间8fq7wneg1#
简短的回答
不,用起来不自然
Callable
而不是Supplier
在CompletableFuture.supplyAsync
. 这个论点几乎完全是关于语义的,所以如果你事后仍然觉得不可信,那也没关系。冗长的回答
这个
Callable
以及Supplier
功能接口/sam类型实际上在功能上是等价的(请原谅双关语),但是它们的起源和预期用途不同。Callable
是作为java.util.concurrent
包裹。这个包出现在java8中lambda表达式的巨大变化之前,最初集中在一系列帮助您编写并发代码的工具上,而没有偏离传统的手工多线程模型。主要目的
Callable
是抽象一个可以在不同线程中执行并返回结果的操作。从Callable
的javadoc:这个
Callable
接口类似于Runnable
,因为它们都是为其示例可能由另一个线程执行的类而设计的。Supplier
是作为java.util.function
包裹。这个包是Java8中上述更改的一个组成部分。它提供了lambda表达式和方法引用可以作为目标的常见函数类型。其中一种类型是不带返回结果的参数的函数(即提供某种类型或参数的函数)
Supplier
函数)。那为什么呢
Supplier
而不是Callable
?CompletableFuture
是对java.util.concurrent
这个包的设计灵感来自于java8中的上述更改,它允许开发人员以一种功能性的、隐式可并行的方式构造代码,而不是显式地处理其中的并发性。它
supplyAsync
方法需要一种方法来提供一个特定类型的结果,它更感兴趣的是这个结果,而不是为了达到这个结果而采取的行动。它也不一定关心特殊的完成(也看到了什么关于。。。下一段)。尽管如此,如果
Runnable
用于没有参数,没有结果的函数接口,不应该Callable
是否用于无参数、单结果功能接口?不一定。
对于没有参数且不返回结果(因此完全通过外部上下文的副作用进行操作)的函数的抽象未包含在中
java.util.function
. 这意味着(有点恼人)Runnable
在需要这种功能接口的地方使用。那支票呢
Exception
可以由Callable.call()
?这是一个很小的迹象表明
Callable
以及Supplier
.一
Callable
是一个可以在另一个线程中执行的操作,它允许您检查其执行的副作用。如果一切顺利,您会得到一个特定类型的结果,但由于在执行某些操作(尤其是在多线程上下文中)时可能会出现异常情况,因此您可能还需要定义和处理此类异常情况。一
Supplier
另一方面是一个函数,您依赖它来提供某种类型的对象。例外情况不一定是您作为产品直接消费者的责任Supplier
. 这是因为:…功能接口通常用于定义多阶段流程中的特定阶段,以创建或更改数据并进行处理
Exception
如果你介意的话,s可以是一个单独的阶段…显式处理
Exception
s显著降低了函数接口、lambda表达式和方法引用的表达能力