承诺是否有缺陷?

0__*_*0__ 5 scala future promise

就像这个问题的作者一样,我试图理解Scala 2.10期货和承诺中用户可见承诺的推理.

特别是,再次回到SIP例子,是不是完全有缺陷:

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()
  }
}
Run Code Online (Sandbox Code Playgroud)

我想象的是调用produceSomething导致运行时异常的情况.因为承诺和生产者 - 未来是完全分离的,这意味着系统挂起,消费者永远不会成功或失败.

因此,使用promises的唯一安全方法需要类似的东西

val producer = future {
  try {
    val r.produceSomething()
    p success r
  } catch {
     case e: Throwable =>
       p failure e
       throw e  // ouch
  }
  continueDoingSomethingUnrelated()
}
Run Code Online (Sandbox Code Playgroud)

这显然容易出错并且冗长.

我可以看到的唯一一个可见的承诺类型 - 在哪里future {}不足 - 是MAD答案中的回调挂钩之一.但SIP的例子对我来说没有意义.

Rex*_*err 7

这就是你很少使用的原因success,failure除非你已经知道某些东西是防弹的.如果你想要防弹,这Try是用于:

val producer = future {
  p complete Try( produceSomething )
  continueDoingSomethingUnrelated()
}
Run Code Online (Sandbox Code Playgroud)

似乎没有必要再次抛出错误; 你已经通过将它包装成答案来处理它,不是吗?(另请注意,如果produceSomething本身返回未来,则可以completeWith改为使用.)


sou*_*ica 4

组合器

您可以用来构建库中尚不存在的Promise其他组合器。Future

您需要 Promise 才能创建其他像这样的组合器。

调整回调

用于Promise使基于回调的 API 适应Future基于 的 API。例如:

def retrieveThing(key: String): Future[Thing] = {
  val p = Promise[Thing]()

  val callback = new Callback() {
    def receive(message: ThingMessage) {
      message.getPayload match {
        case t: Thing =>
          p success t        
        case err: SystemErrorPayload =>
          p failure new Exception(err.getMessage)
      }
    }
  }

  thingLoader.load(key, callback, timeout)
  p.future
}
Run Code Online (Sandbox Code Playgroud)

同步器

使用 构建同步器Promise。例如,为昂贵的操作返回缓存值,或计算它,但不要对同一个键计算两次:

private val cache = new ConcurrentHashMap[String, Promise[T]]

def getEntry(key: String): Future[T] = {
  val newPromise = Promise[T]()
  val foundPromise = cache putIfAbsent (key, newPromise)

  if (foundPromise == null) {
    newPromise completeWith getExpensive(key)
    newPromise.future
  } else {
    foundPromise.future
  }
}
Run Code Online (Sandbox Code Playgroud)