CompletableFuture supplyAsync [英] CompletableFuture supplyAsync

查看:2141
本文介绍了CompletableFuture supplyAsync的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

CompletableFuture<Void> runAsync(Runnable runnable) 
CompletableFuture<U> supplyAsync(Supplier<U> supplier)

有人知道为什么选择使用界面供应商吗?使用Callable是否更自然,这类似于Runnable的返回值?那是因为供应商没有抛出无法处理的异常吗?

解决方案

简短答案

否,使用Callable代替CompletableFuture.supplyAsync中的Supplier并不自然.该论点几乎完全是关于语义的,因此如果您之后仍然感到不满意,也可以.

好答案

CallableSupplier功能接口/SAM类型实际上在功能上等效(对双关语),但是它们的起源和预期用途不同.

Callable java.util.concurrent软件包的一部分.该程序包是在Java 8中的lambda表达式发生巨大变化之前发生的,最初集中在一系列工具上,这些工具可帮助您编写并发代码,而又不会偏离经典的动手多线程模型.

Callable的主要目的是抽象一个可以在不同线程中执行并返回结果的动作.从Callable的Javadoc:

Callable界面与Runnable相似,两者都是 设计用于其实例可能由以下对象执行的类 另一个线程.

Supplier java.util.function软件包的一部分.该软件包是上述Java 8更改的组成部分.它提供了lambda表达式和方法引用可以作为目标的通用功能类型.

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

那为什么要Supplier而不是Callable?

CompletableFuturejava.util.concurrent程序包的新增内容的一部分,其受Java 8中前述更改的启发,使开发人员可以以功能性,隐式可并行化的方式构造其代码,而不是在其中明确地处理并发性.

它的supplyAsync方法需要一种方法来提供特定类型的结果,并且它对该结果更感兴趣,而不是为达到该结果而采取的措施.它也不一定关心出色的完成效果(另请参见下面的有关... 的内容)

.

仍然,如果将Runnable用作无参数,无结果的功能接口,是否应该将Callable用作无参数,无结果的功能接口?

不一定.

java.util.function中不包含对没有参数且不返回结果(因此完全通过外部上下文的副作用进行操作)的函数的抽象.这意味着Runnable(有点令人讨厌)在需要这种功能接口的任何地方使用.

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

这只是CallableSupplier之间预期的语义差异的一个小信号.

A Callable是可以在另一个线程中执行的操作,它使您可以检查其执行后的副作用.如果一切顺利,您将得到特定类型的结果,但是由于执行某些操作时可能会出现异常情况(尤其是在多线程上下文中),因此您可能还希望定义和处理此类异常情况.

另一方面,

A Supplier是您提供某种类型的对象所依赖的功能.特殊情况不一定要作为Supplier的直接使用者承担责任.这是因为:

  1. ...功能性接口通常用于在多阶段创建或变异数据的过程中定义特定阶段,如果您需要的话,处理Exception可以是一个单独的阶段
  2. ...显式处理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 to Runnable, 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:

  1. ...functional interfaces are often used for defining a specific stage in a multi-stage process for creating or mutating data, and handling Exceptions can be a separate stage, in case you care
  2. ...explicitly handling Exceptions significantly reduces the expressive powers of functional interfaces, lambda expressions and method references

这篇关于CompletableFuture supplyAsync的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆