问题
I'm using Play Framework 2.1.1 with an external java library that produces a java.util.concurrent.Future result. I'm using the scala future's as opposed to Akka which I think is the right thing to do as of Play 2.1. How can I wrap the java.util.concurrent.Future up into a scala.concurrent.Future while still keeping the code non-blocking?
def geConnection() : Connection = {
// blocking with get
connectionPool.getConnectionAsync().get(30000, TimeUnit.MILLISECONDS)
}
The above code returns a connection but uses a get so it becomes blocking
def getConnectionFuture() : Future[Connection] = {
future {
// how to remove blocking get and return a scala future?
connectionPool.getConnectionAsync().get(30000, TimeUnit.MILLISECONDS)
}
}
Ideally I want a scala function that returns the connection as a future like the code above but without the code blocking via the get. What else do I need to put into the function to make it non blocking.
Any pointers would be great.
回答1:
import java.util.concurrent.{Future => JFuture}
import scala.concurrent.{Future => SFuture}
You can't wrap JFuture with SFuture without blocking since there is a callback in SFuture
(onComplete
) and there is only blocking get
in JFuture
.
All you can do is to create additional thread and block it with get
, then complete Promise with result of get
.
val jfuture: JFuture[T] = ???
val promise = Promise[T]()
new Thread(new Runnable { def run() { promise.complete(Try{ jfuture.get }) }}).start
val future = promise.future
You could check isDone
in endless loop, but I don't think it is better then blocking.
回答2:
Future {
blocking {
jfuture.get
}
}
This lets the ExecutionContext know that what you are doing is going to block, giving it a chance to allocate more threads. If you do not include blocking { }
then you may run out of threads.
回答3:
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
}
回答4:
The scala-java8-compat library provides converters between java8 and Scala Futures.
Specifically, you can use FutureConverters.toScala(connectionPool.getConnectionAsync()) to convert the java.util.concurrent.Future
to scala.concurrent.Future
来源:https://stackoverflow.com/questions/17215421/scala-concurrent-future-wrapper-for-java-util-concurrent-future