【发布时间】:2013-08-24 07:01:28
【问题描述】:
我正在为 Futures 编写 scala java 互操作包装器,但我不知道实现 scala.concurrent.Future.onComplete (http://www.scala-lang.org/api/current/index.html#scala.concurrent.Future) 的正确方法。这可能有效:
def onComplete[U](func: Try[T] => U)(implicit executor: ExecutionContext): Unit = {
executor.execute(new Runnable {
@tailrec
def run = value match {
case Some(t) => func(t)
case None => { Thread.sleep(100); run }
}
})
}
但是Asynchronous IO in Scala with futures 建议当我必须阻止时,我应该将代码的相关部分传递给 scala.concurrent.blocking 让 ExecutionContext 知道发生了什么。问题是当我用阻塞 {} 包围值 match{...} 时,它不再是尾调用。
众所周知的正确方法是什么?
编辑:为了完整起见,这里是整个包装类:
class JavaFutureWrapper[T](val jf: java.util.concurrent.Future[T]) extends scala.concurrent.Future[T] {
def isCompleted = jf.isDone
def result(atMost: Duration)(implicit permit: CanAwait): T =
atMost match { case Duration(timeout, units) => jf.get(timeout, units) }
def onComplete[U](func: Try[T] => U)(implicit executor: ExecutionContext): Unit = {
executor.execute(new Runnable {
@tailrec
def run = value match {
case Some(t) => func(t)
case None => { Thread.sleep(100); run }
}
})
}
def ready(atMost: Duration)(implicit permit: CanAwait): this.type = atMost match {
case Duration(timeout, units) => {
jf.get(timeout, units)
this
}
}
def value: Option[Try[T]] = (jf.isCancelled, jf.isDone) match {
case (true, _) => Some(Failure(new Exception("Execution was cancelled!")))
case (_, true) => Some(Success(jf.get))
case _ => None
}
}
【问题讨论】:
-
你能指出什么是Java API吗?例如,
value来自哪里?为什么要让线程休眠 100 毫秒?换句话说,您的潜在阻塞代码在哪里? -
我已经为你粘贴了整个包装类。睡眠是为了防止紧密循环,因为我轮询 Java 未来是否已经完成。整个 run 方法将阻塞,直到 jf 决定它是完成还是取消。
-
如果你只用阻塞包围 Thread.sleep() 怎么办?另一个想法是使用一段时间而不是递归调用。
-
哎呀,我没想到只围着睡觉,我想我们可能有一个赢家。 ExecutionContexts 应该足够聪明,可以处理快速退出然后又回到阻塞部分,对吧?
标签: scala java.util.concurrent