CompletableFuture supplyAsync [英] CompletableFuture supplyAsync
问题描述
我刚刚开始探索Java 8的一些并发特性.让我有些困惑的是这两个静态方法:
CompletableFuture<Void> runAsync(Runnable runnable)
CompletableFuture<U> supplyAsync(Supplier<U> supplier)
有人知道为什么选择使用界面供应商吗?使用Callable是否更自然,这类似于Runnable的返回值?那是因为供应商没有抛出无法处理的异常吗?
简短答案
否,使用Callable
代替CompletableFuture.supplyAsync
中的Supplier
并不自然.该论点几乎完全是关于语义的,因此如果您之后仍然感到不满意,也可以.
好答案
Callable
和Supplier
功能接口/SAM类型实际上在功能上等效(对双关语),但是它们的起源和预期用途不同.
Callable
是java.util.concurrent
软件包的一部分.该程序包是在Java 8中的lambda表达式发生巨大变化之前发生的,最初集中在一系列工具上,这些工具可帮助您编写并发代码,而又不会偏离经典的动手多线程模型.
Callable
的主要目的是抽象一个可以在不同线程中执行并返回结果的动作.从Callable
的Javadoc:
Callable
界面与Runnable
相似,两者都是 设计用于其实例可能由以下对象执行的类 另一个线程.
Supplier
是java.util.function
软件包的一部分.该软件包是上述Java 8更改的组成部分.它提供了lambda表达式和方法引用可以作为目标的通用功能类型.
一种这样的类型是没有返回结果的参数的函数(即提供某种类型的函数或Supplier
函数).
那为什么要Supplier
而不是Callable
?
CompletableFuture
是java.util.concurrent
程序包的新增内容的一部分,其受Java 8中前述更改的启发,使开发人员可以以功能性,隐式可并行化的方式构造其代码,而不是在其中明确地处理并发性.
它的supplyAsync
方法需要一种方法来提供特定类型的结果,并且它对该结果更感兴趣,而不是为达到该结果而采取的措施.它也不一定关心出色的完成效果(另请参见下面的有关... 的内容)
仍然,如果将Runnable
用作无参数,无结果的功能接口,是否应该将Callable
用作无参数,无结果的功能接口? >
不一定.
java.util.function
中不包含对没有参数且不返回结果(因此完全通过外部上下文的副作用进行操作)的函数的抽象.这意味着Runnable
(有点令人讨厌)在需要这种功能接口的任何地方使用.
Callable.call()
可以抛出的已检查Exception
怎么样?
这只是Callable
和Supplier
之间预期的语义差异的一个小信号.
A Callable
是可以在另一个线程中执行的操作,它使您可以检查其执行后的副作用.如果一切顺利,您将得到特定类型的结果,但是由于执行某些操作时可能会出现异常情况(尤其是在多线程上下文中),因此您可能还希望定义和处理此类异常情况.
A Supplier
是您提供某种类型的对象所依赖的功能.特殊情况不一定要作为Supplier
的直接使用者承担责任.这是因为:
- ...功能性接口通常用于在多阶段创建或变异数据的过程中定义特定阶段,如果您需要的话,处理
Exception
可以是一个单独的阶段 - ...显式处理
Exception
会大大降低功能接口,lambda表达式和方法引用的表达力
I've just started exploring some concurrency features of Java 8. One thing confused me a bit is these two static methods:
CompletableFuture<Void> runAsync(Runnable runnable)
CompletableFuture<U> supplyAsync(Supplier<U> supplier)
Do anyone know why they choose to use interface Supplier? Isn't it more natural to use Callable, which is the analogy of Runnable that returns a value? Is that because Supplier doesn't throw an Exception that couldn't be handled?
Short answer
No, it's not more natural to use Callable
instead of Supplier
in CompletableFuture.supplyAsync
. The argument is almost entirely about semantics, so it's OK if you still feel unconvinced afterwards.
Long answer
The Callable
and Supplier
functional interfaces/SAM types are practically equivalent in function (pardon the pun), but their origin and intended use differ.
Callable
was created as part of the java.util.concurrent
package. That package came before the vast changes around lambda expressions in Java 8 and originally concentrated on a range of tools that helped you write concurrent code, without deviating much from the classic model of hands-on multithreading.
The main purpose of Callable
was to abstract an action that can be executed in a different thread and that returns a result. From Callable
's Javadoc:
The
Callable
interface is similar toRunnable
, in that both are designed for classes whose instances are potentially executed by another thread.
Supplier
was created as part of the java.util.function
package. That package came as an integral part of the aforementioned changes in Java 8. It provides common functional types that can be targeted by lambda expressions and method references.
One such type is a function without parameters that returns a result (i.e. a function that supplies some type or a Supplier
function).
So why Supplier
and not Callable
?
CompletableFuture
is part of additions to the java.util.concurrent
package that were inspired by the aforementioned changes in Java 8 and that allow the developer to construct his code in a functional, implicitly parallelizable manner, instead of explicitly handling concurrency within it.
Its supplyAsync
method needs a way to provide a result of a specific type and its more interested in this result, and not in the action taken to reach this result. It also doesn't necessarily care about exceptional completion (also see the What about the... paragraph below).
Still, if Runnable
is used for no-parameters, no-result functional interface, shouldn't Callable
be used for no-parameters, single-result functional interface?
Not necessarily.
An abstraction for a function that does not have a parameter and does not return a result (and therefore operates entirely through side effects on outside context) was not included in java.util.function
. This means that (somewhat annoyingly) Runnable
is used wherever such a functional interface is needed.
What about the checked Exception
that can be thrown byCallable.call()
?
It's a small sign of the intended semantic difference between Callable
and Supplier
.
A Callable
is an action that can be executed in another thread, and that allows you to inspect its side effects as a result of its execution. If all goes well, you get a result of a specific type, but because exceptional situations can arise when executing some actions (especially in multithreaded context), you may also want to define and handle such exceptional situations.
A Supplier
on the other hand is a function on which you rely for supplying objects of some type. Exceptional situations should not necessarily be made your responsibility as the direct consumer of the Supplier
. This is so because:
- ...functional interfaces are often used for defining a specific stage in a multi-stage process for creating or mutating data, and handling
Exception
s can be a separate stage, in case you care - ...explicitly handling
Exception
s significantly reduces the expressive powers of functional interfaces, lambda expressions and method references
这篇关于CompletableFuture supplyAsync的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!