用于java.util.concurrent.Future的scala.concurrent.Future包装器

时间:2013-06-20 13:51:09

标签: java scala concurrency playframework-2.1 future

我正在使用Play Framework 2.1.1和一个生成java.util.concurrent.Future结果的外部java库。我正在使用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阻止代码。我还需要在函数中添加什么才能使其无阻塞。

任何指针都会很棒。

4 个答案:

答案 0 :(得分:21)

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

由于SFutureonComplete)中存在回调,并且只有阻止get,因此您无法阻止JFuture SFuture {{}}} JFuture

您所能做的就是创建其他主题并使用get阻止它,然后使用get的结果完成Promise

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,但我认为它不会比阻止更好。

答案 1 :(得分:5)

Future {
  blocking {
    jfuture.get
  }
}

这使得ExecutionContext知道你正在做的事情会阻塞,让它有机会分配更多的线程。如果您不包含blocking { },那么您可能会用完线程。

答案 2 :(得分:2)

     import java.util.concurrent.{Future => JFuture}
     import scala.concurrent.ExecutionContext.Implicits.global
     import scala.concurrent.Future
     import scala.util.Try

     object JFuture2SFuture {
        val jFuture: JFuture[Int] = ???
        val promise = Promise[Int]()
        Future { promise.complete(Try(jFuture.get)) } //it is non blocking 
        val sFuture:Future[Int] = promise.future

     }

答案 3 :(得分:0)

scala-java8-compat库提供java8和Scala Futures之间的转换器。

具体来说,您可以使用FutureConverters.toScala(connectionPool.getConnectionAsync())java.util.concurrent.Future转换为scala.concurrent.Future