scala.concurrent.Future wrapper for java.util.concurrent.Future

我正在使用Play Framework 2.1.1和一个外部java库,该库产生java.util.concurrent.Future结果。我正在使用scala future,而不是Akka,我认为从Play 2.1开始,这是正确的做法。如何将java.util.concurrent.Future包装成scala.concurrent.Future,同时仍然保持代码不阻塞?

def geConnection() : Connection = {
  // blocking with get
  connectionPool.getConnectionAsync().get(30000, TimeUnit.MILLISECONDS)
}

上面的代码返回一个连接,但使用get,所以它变成了阻塞

def getConnectionFuture() : Future[Connection] = {
  future {
    // how to remove blocking get and return a scala future?
    connectionPool.getConnectionAsync().get(30000, TimeUnit.MILLISECONDS)
  }
}

理想情况下,我想要一个 scala 函数,它将连接作为未来返回,就像上面的代码一样,但没有通过 get 阻塞代码。我还需要在函数中放入什么才能使其不阻塞。

任何指针都会很棒。


答案 1
import java.util.concurrent.{Future => JFuture}
import scala.concurrent.{Future => SFuture}

您不能在不阻塞的情况下将 JFutureSFuture 包装在一起,因为 () 中有一个回调,而 .SFutureonCompletegetJFuture

您所能做的就是创建额外的线程并使用 阻止它,然后用 的结果完成承诺getget

val jfuture: JFuture[T] = ???
val promise = Promise[T]()
new Thread(new Runnable { def run() { promise.complete(Try{ jfuture.get }) }}).start
val future = promise.future

你可以签入无限循环,但我认为它并不比阻止更好。isDone


答案 2
Future {
  blocking {
    jfuture.get
  }
}

这让执行上下文知道你正在做的事情将被阻止,让它有机会分配更多的线程。如果不包含,则可能会耗尽线程。blocking { }


推荐