scala.concurrent.Promise 的用例是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13381134/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 04:43:18  来源:igfitidea点击:

What are the use cases of scala.concurrent.Promise?

scalaconcurrency

提问by xiefei

I am reading SIP-14and the concept of Futuremakes perfect sense and easy to understand. But have two questions about Promise:

我正在阅读SIP-14并且这个概念Future非常有意义且易于理解。但是有两个问题关于Promise

  1. The SIP says Depending on the implementation, it may be the case that p.future == p. How can this be? Are Futureand Promisenot two different types?

  2. When should we use a Promise? The example producer and consumercode :

    import scala.concurrent.{ future, promise }
    val p = promise[T]
    val f = p.future
    
    val producer = future {
        val r = produceSomething()
        p success r
        continueDoingSomethingUnrelated()
    }
    val consumer = future {
        startDoingSomething()
        f onSuccess {
            case r => doSomethingWithResult()
        }
    }
    
  1. SIP 说Depending on the implementation, it may be the case that p.future == p。怎么会这样?是FuturePromise不是两种不同的类型?

  2. 我们Promise什么时候应该使用? 示例producer and consumer代码:

    import scala.concurrent.{ future, promise }
    val p = promise[T]
    val f = p.future
    
    val producer = future {
        val r = produceSomething()
        p success r
        continueDoingSomethingUnrelated()
    }
    val consumer = future {
        startDoingSomething()
        f onSuccess {
            case r => doSomethingWithResult()
        }
    }
    

is easy to read but do we really need to write like that? I tried to implement it only with Future and without Promise like this:

很容易阅读,但我们真的需要那样写吗?我试图只用 Future 而没有 Promise 来实现它,如下所示:

val f = future {
   produceSomething()
}

val producer = future {
   continueDoingSomethingUnrelated()
}

startDoingSomething()

val consumer = future {
  f onSuccess {
    case r => doSomethingWithResult()
  }
}

What is the difference between this and the given example and what makes a Promise necessary?

这和给定的例子有什么区别,是什么让 Promise 成为必要?

回答by Marius Danila

The Promise and Future are complementary concepts. The Future is a value which will be retrieved, well, sometime in the future and you can do stuff with it when that event happens. It is, therefore, the read or out endpoint of a computation - it is something that you retrieve a value from.

Promise 和 Future 是互补的概念。Future 是一个值,它将在未来某个时间被检索,当该事件发生时,您可以用它做任何事情。因此,它是计算的读取或输出端点 - 您可以从中检索值。

A Promise is, by analogy, the writing side of the computation. You create a promise which is the place where you'll put the result of the computation and from that promise you get a future that will be used to read the result that was put into the promise. When you'll complete a Promise, either by failure or success, you will trigger all the behavior which was attached to the associated Future.

以此类推,Promise 是计算的写入端。您创建了一个承诺,它是您放置计算结果的地方,并从该承诺中获得一个未来,该未来将用于读取放入承诺中的结果。当您通过失败或成功完成 Promise 时,您将触发所有附加到关联 Future 的行为。

Regarding your first question, how can it be that for a promise p we have p.future == p. You can imagine this like a single-item buffer - a container which is initially empty and you can afterwords store one value which will become its content forever. Now, depending on your point of view this is both a Promise and a Future. It is promise for someone who intends to write the value in the buffer. It is a future for someone who waits for that value to be put in the buffer.

关于你的第一个问题,对于我们有的承诺 p 怎么可能p.future == p。你可以把它想象成一个单项缓冲区——一个最初是空的容器,你可以在之后存储一个将永远成为其内容的值。现在,根据您的观点,这既是 Promise 也是未来。对于打算在缓冲区中写入值的人来说,这是一种承诺。对于等待将该值放入缓冲区的人来说,这是一个未来。

Specifically, for the Scala concurrent API, if you take a look at the Promise trait in hereyou can see how the methods from the Promise companion object are implemented :

具体来说,对于 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))

}

Now, those implementation of promises, DefaultPromise and KeptPromise can be found here. They both extend a base little trait which happens to have the same name, but it is located in a different package:

现在,可以在这里找到那些承诺的实现, DefaultPromise 和 KeptPromise 。它们都扩展了一个碰巧具有相同名称的基本小特征,但它位于不同的包中:

private[concurrent] trait Promise[T] extends scala.concurrent.Promise[T] with scala.concurrent.Future[T] {
  def future: this.type = this
}

So you can see what they mean by p.future == p.

因此,您可以了解它们的含义p.future == p

DefaultPromiseis the buffer I was referring above, while KeptPromiseis a buffer with the value put in from its very creation.

DefaultPromise是我在上面提到的缓冲区,而KeptPromise是一个缓冲区,其值是从其创建时放入的。

Regarding your example, the future block you use there actually creates a promise behind the scenes. Let's look at the definition of futurein here:

关于你的例子,你在那里使用的未来块实际上在幕后创造了一个承诺。让我们看的定义future这里

def future[T](body: =>T)(implicit execctx: ExecutionContext): Future[T] = Future[T](body)

By following the chain of methods you end up in the impl.Future:

通过遵循方法链,您最终会进入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
  }
}

So, as you can see, the result you get from your producer block gets poured into a promise.

因此,如您所见,您从生产者块中获得的结果被注入了一个承诺中。

LATER EDIT:

稍后编辑

Regarding the real-world use: Most of the time you won't deal with promises directly. If you'll use a library which performs asynchronous computation then you'll just work with the futures returned by the library's methods. Promises are, in this case, created by the library - you're just working with the reading end of what those methods do.

关于现实世界的使用:大多数时候你不会直接处理承诺。如果您将使用执行异步计算的库,那么您将只使用库方法返回的期货。在这种情况下,Promise 是由库创建的 - 您只是在阅读这些方法所做的工作。

But if you need to implement your own asynchronous API you'll have to start working with them. Suppose you need to implement an async HTTP client on top of, lets say, Netty. Then your code will look somewhat like this

但是,如果您需要实现自己的异步 API,则必须开始使用它们。假设您需要在 Netty 之上实现一个异步 HTTP 客户端。然后你的代码看起来有点像这样

    def makeHTTPCall(request: Request): Future[Response] = {
        val p = Promise[Response]
        registerOnCompleteCallback(buffer => {
            val response = makeResponse(buffer)
            p success response
        })
        p.future
    }