用于java.util.concurrent.Future的scala.concurrent.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阻止代码。 我还需要在函数中添加什么才能使其无阻塞。
任何指针都会很棒。
import java.util.concurrent.{Future => JFuture} import scala.concurrent.{Future => SFuture}
你不能在没有阻塞的情况下用SFuture
包装JFuture
,因为在SFuture
有一个回调( onComplete
)并且在JFuture
只有阻塞get
。
你所能做的就是创建额外的线程并用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
,但我不认为它比阻塞更好。
Future { blocking { jfuture.get } }
这使得ExecutionContext知道你正在做的事情将会阻塞,让它有机会分配更多的线程。 如果你不包含blocking { }
那么你可能会用完线程。
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 }
scala-java8-compat库提供java8和Scala Futures之间的转换器。
具体来说,您可以使用FutureConverters.toScala(connectionPool.getConnectionAsync())
将java.util.concurrent.Future
转换为scala.concurrent.Future