承诺和未来是相辅相成的概念。Future是一个可以在将来的某个时间检索的值,当该事件发生时,您可以使用它进行处理。因此,它是计算的读取或输出端点-您可以从中检索值。
以此类推,Promise是计算的编写方。您创建一个promise,在该位置放置计算结果,然后从该promise中获得一个future,该future将用于读取放入promise中的结果。当您通过失败或成功完成一个Promise时,您将触发关联到Future的所有行为。
关于您的第一个问题,我们有一个诺言p怎么可能呢p.future == p
?您可以想象这就像一个单项缓冲区–一个最初为空的容器,您可以在后记中存储一个值,该值将永远成为其内容。现在,根据您的观点,这既是一个承诺,也是一个未来。对于打算将值写入缓冲区的人来说,这是一个承诺。对于等待该值放入缓冲区的人来说,这是一个未来。
具体来说,对于Scala并发API,如果您在此处查看Promise特性,则可以看到Promise伴随对象的方法是如何实现的:
object Promise {
/** Creates a promise object which can be completed with a value.
*
* @tparam T the type of the value in the promise
* @return the newly created `Promise` object
*/
def apply[T](): Promise[T] = new impl.Promise.DefaultPromise[T]()
/** Creates an already completed Promise with the specified exception.
*
* @tparam T the type of the value in the promise
* @return the newly created `Promise` object
*/
def failed[T](exception: Throwable): Promise[T] = new impl.Promise.KeptPromise[T](Failure(exception))
/** Creates an already completed Promise with the specified result.
*
* @tparam T the type of the value in the promise
* @return the newly created `Promise` object
*/
def successful[T](result: T): Promise[T] = new impl.Promise.KeptPromise[T](Success(result))
}
现在,可以在此处找到Promise的那些实现,即DefaultPromise和KeptPromise 。它们都扩展了一个基本的小特征,恰好具有相同的名称,但是它位于不同的包中:
private[concurrent] trait Promise[T] extends scala.concurrent.Promise[T] with scala.concurrent.Future[T] {
def future: this.type = this
}
这样您就可以了解它们的含义p.future == p
。
DefaultPromise
是上面我所指的缓冲区,而KeptPromise
缓冲区是从其创建时就已放入值的缓冲区。
对于您的示例,在那里使用的Future块实际上在幕后创造了希望。让我们看的定义future
在这里:
def future[T](body: =>T)(implicit execctx: ExecutionContext): Future[T] = Future[T](body)
通过遵循方法链,您最终会遇到impl.Future:
private[concurrent] object Future {
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) }
}
}
}
def apply[T](body: =>T)(implicit executor: ExecutionContext): scala.concurrent.Future[T] = {
val runnable = new PromiseCompletingRunnable(body)
executor.execute(runnable)
runnable.promise.future
}
}
因此,正如您所看到的,从生产者模块中获得的结果被注入了承诺。
之后编辑:
关于实际用途:大多数情况下,您不会直接处理承诺。如果您要使用执行异步计算的库,那么就可以使用该库的方法返回的期货。在这种情况下,承诺是由库创建的-您只是在阅读这些方法的作用。
但是,如果您需要实现自己的异步API,则必须开始使用它们。假设您需要在Netty之上实现一个异步HTTP客户端。然后您的代码将看起来像这样
def makeHTTPCall(request: Request): Future[Response] = {
val p = Promise[Response]
registerOnCompleteCallback(buffer => {
val response = makeResponse(buffer)
p success response
})
p.future
}