需要澄清 Scala 中的期货和承诺
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18960339/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Clarification needed about futures and promises in Scala
提问by nish1013
I am trying to get my head around Scala's promise and future constructs.
我正在努力了解 Scala 的承诺和未来的构造。
I've been reading Futures and Promisesin Scala Documentation and am a bit confused as I've got a feeling that the concepts of promises and futures are mixed up.
我一直在阅读Scala 文档中的Futures and Promises并且有点困惑,因为我觉得 promises 和 futures 的概念混淆了。
In my understanding a promise is a container that we could populate value in a later point. And future is some sort of an asynchronous operation that would complete in a different execution path.
在我的理解中,promise 是一个容器,我们可以在稍后填充值。而 future 是某种异步操作,它将在不同的执行路径中完成。
In Scala we can obtain a result using the attached callbacks to future.
在 Scala 中,我们可以使用附加的回调函数获取结果。
Where I'm lost is how promise has a future?
我迷失的地方是承诺如何有未来?
I have read about these concepts in Clojure too, assuming that promise and future have some generic common concept, but it seems like I was wrong.
我也在 Clojure 中阅读了这些概念,假设 promise 和 future 有一些通用的通用概念,但似乎我错了。
A promise p completes the future returned by p.future. This future is specific to the promise p. Depending on the implementation, it may be the case that p.future eq p.
承诺 p 完成 p.future 返回的未来。这个未来是特定于承诺 p 的。根据实现的不同,可能会出现 p.future eq p.
val p = promise[T]
val f = p.future
回答by axel22
You can think of futures and promises as two different sides of a pipe. On the promise side, data is pushed in, and on the future side, data can be pulled out.
您可以将期货和承诺视为管道的两个不同侧面。在promise端,数据被推入,在future端,数据可以被拉出。
And future is some sort of an asynchronous operation that would complete in a different execution path.
而 future 是某种异步操作,它将在不同的执行路径中完成。
Actually, a future is a placeholder objectfor a value that may be become available at some point in time, asynchronously. It is not the asynchronous computation itself.
实际上,future 是一个值的占位符对象,该值可能在某个时间点异步可用。它不是异步计算本身。
The fact that there is a future constructor called futurethat returns such a placeholder object andspawns an asynchronous computation that completes this placeholder object does not mean that the asynchronous computation is called a future. There are also other future constructors/factory methods.
有一个 future 构造函数被调用future,它返回这样一个占位符对象并产生一个异步计算来完成这个占位符对象并不意味着异步计算被称为future。还有其他未来的构造函数/工厂方法。
But the point I do not get is how promise has a future?
但我不明白的一点是承诺如何有未来?
To divide promises and futures into 2 separate interfaces was a design decision. You could have these two under the same interface Future, but that would then allow clients of futures to complete them instead of the intended completer of the future. This would cause unexpected errors, as there could be any number of contending completers.
将 promises 和 futures 分成 2 个独立的接口是一个设计决定。您可以将这两个放在同一个界面下Future,但这将允许期货的客户完成它们,而不是未来的预期完成者。这会导致意外错误,因为可能有任意数量的竞争完成者。
E.g. for the asynchronous computation spawned by the futureconstruct, it would no longer be clear whether it has to complete the promise, or if the client will do it.
例如,对于future构造产生的异步计算,它是否必须完成承诺,或者客户端是否会这样做将不再清楚。
Futures and promises are intended to constrain the flow of data in the program. The idea is to have a future client that subscribes to the data to act on it once the data arrives. The role of the promise client is to provide that data. Mixing these two roles can lead to programs that are harder to understand or reason about.
期货和承诺旨在限制程序中的数据流。这个想法是让未来的客户端订阅数据,以便在数据到达后对其进行操作。承诺客户端的作用是提供该数据。混合这两个角色会导致程序更难理解或推理。
You might also ask why the Promisetrait does not extend Future. This is another design decision to discourage programmers from blindly passing Promises to clients where they should upcast the Promiseto Future(this upcast is prone to be left out, whereas having to explicitly call futureon the promise ensures you call it every time). In other words, by returning a promise you are giving the right to complete it to somebody else, and by returning the future you are giving the right to subscribe to it.
您可能还会问为什么Promisetrait 没有扩展Future。这是另一个设计决定从盲目传球劝阻程序员Promises到客户,他们应该上溯造型的Promise来Future(这上溯造型很容易被排除在外,而具有显式调用future上的承诺,确保你调用每次它)。换句话说,通过返回承诺,您将完成它的权利授予其他人,通过返回未来,您将获得订阅它的权利。
EDIT:
编辑:
If you would like to learn more about futures, Chapter 4 in the Learning Concurrent Programming in Scala book describes them in detail. Disclaimer: I'm the author of the book.
如果您想了解更多有关 future 的信息,请参阅 Learning Concurrent Programming in Scala 一书中的第 4 章详细介绍了它们。免责声明:我是这本书的作者。
回答by subsub
The difference between the two is that futures are usually centered around the computation while promises are centered around data.
两者之间的区别在于,期货通常以计算为中心,而承诺以数据为中心。
It seems your understanding matches this, but let me explain what I mean:
看来您的理解与此相符,但让我解释一下我的意思:
In both scala and clojure futuresare (unless returned by some other function/method) created with some computation:
在 scala 和 clojure 中,期货(除非由某些其他函数/方法返回)是通过一些计算创建的:
// scala
future { do_something() }
;; clojure
(future (do-something))
In both cases the "return-value" of the future can only be read (without blocking) only after the computation has terminated. When this is the case is typically outside the control of the programmer, as the computation gets executed in some thread (pool) in the background.
在这两种情况下,只有在计算终止后才能读取未来的“返回值”(无阻塞)。这种情况通常不在程序员的控制范围内,因为计算是在后台的某个线程(池)中执行的。
In contrast in both cases promisesare an initially empty container, which can later be filled (exactly once):
相比之下,在这两种情况下,promise最初都是一个空容器,以后可以填充(恰好一次):
// scala
val p = promise[Int]
...
p success 10 // or failure Exception()
;; clojure
(def p (promise))
(deliver p 10)
Once this is the case it can be read.
一旦出现这种情况,就可以读取了。
Reading the futures and promises is done through derefin clojure (and realized?can be used to check if derefwill block). In scala reading is done through the methods provided by the Futuretrait. In order to read the result of a promise we thus have to obtain an object implementing Future, this is done by p.future. Now if the trait Futureis implemented by a Promise, then p.futurecan return thisand the two are equal. This is purely a implementation choice and does not change the concepts. So you were not wrong!In any case Futures are mostly dealt with using callbacks.
读取期货和承诺是deref在 clojure 中完成的(realized?可用于检查是否deref会阻塞)。在 Scala 中,读取是通过Futuretrait提供的方法完成的。为了读取承诺的结果,我们必须获得一个实现 Future 的对象,这是由p.future. 现在,如果特征Future由 a 实现Promise,则p.future可以返回this并且两者相等。这纯粹是一种实现选择,不会改变概念。所以你没有看错!在任何情况下,Future 主要是使用回调来处理的。
At this point it might be worthwhile to reconsider the initial characterization of the two concepts:
在这一点上,重新考虑这两个概念的初始特征可能是值得的:
Futures represent a computation that will produce a resultat some point. Let's look at one possible implementation: We run the code in some thread(pool) and once its done, we arrange use the return value to fulfill a promise. So reading the result of the future is reading a promise; This is clojure's way of thinking (not necessarily of implementation).
Futures 表示将在某个时刻产生结果的计算。让我们看看一种可能的实现:我们在某个线程(池)中运行代码,一旦完成,我们安排使用返回值来实现承诺。所以阅读未来的结果就是阅读一个承诺;这是 clojure 的思维方式(不一定是实现方式)。
On the other hand a promise represents a value that will be filled at some point. When it gets filled this means that some computation produced a result. So in a way this is like a future completing, so we should consume the value in the same way, using callbacks; This is scala's way of thinking.
另一方面,promise 表示将在某个时候填充的值。当它被填满时,这意味着某些计算产生了结果。所以在某种程度上这就像一个未来完成,所以我们应该以同样的方式使用这个值,使用回调;这是scala的思维方式。
回答by goral
Note that under the hood Futureis implemented in terms of Promiseand this Promiseis completed with the body you passed to your Future:
需要注意的是引擎盖下Future来讲实现Promise,这Promise是完成了,你传递给你的身体Future:
def apply[T](body: =>T): Future[T] = impl.Future(body) //here I have omitted the implicit ExecutorContext
impl.Future is an implementation of Futuretrait:
impl.Future 是Futuretrait 的一个实现:
def apply[T](body: =>T)(implicit executor: ExecutionContext): scala.concurrent.Future[T] =
{
val runnable = new PromiseCompletingRunnable(body)
executor.prepare.execute(runnable)
runnable.promise.future
}
Where PromiseCompletingRunnablelooks like this:
哪里PromiseCompletingRunnable看起来像这样:
class PromiseCompletingRunnable[T](body: => T) extends Runnable {
val promise = new Promise.DefaultPromise[T]()
override def run() = {
promise complete {
try Success(body) catch { case NonFatal(e) => Failure(e) }
}
} }
So you see even though they are seperate concepts that you can make use of independently in reality you can't get Futurewithout using Promise.
因此,您会看到即使它们是单独的概念,您可以在现实中独立使用它们,但如果Future不使用Promise.

