我使用Play Framework 2.1.1和一个外部java库,该库生成java.util.concurrent。这是未来的结果。我使用的是scala future,而不是Akka,我认为从Play 2.1开始,这是正确的做法。我如何包装java.util.concurrent。未来升级为scala.concurrent。未来,同时仍然保持代码不阻塞?
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.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
}
Future {
blocking {
jfuture.get
}
}
这让ExecutionContext知道您正在做的事情将被阻塞,从而有机会分配更多线程。如果您不包含阻塞{}
,那么您可能会用完线程。
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
,但我认为这并不比阻塞更好。