framework - scala.concurrent.Future wrapper para java.util.concurrent.Future
play framework return file (4)
Estoy usando Play Framework 2.1.1 con una biblioteca java externa que produce un resultado java.util.concurrent.Future. Estoy usando el futuro de Scala en lugar de Akka, que creo que es lo correcto en Play 2.1. ¿Cómo puedo envolver el java.util.concurrent.Future en un scala.concurrent.Future mientras mantengo el código sin bloquear?
def geConnection() : Connection = {
// blocking with get
connectionPool.getConnectionAsync().get(30000, TimeUnit.MILLISECONDS)
}
El código anterior devuelve una conexión pero utiliza un get para que se bloquee.
def getConnectionFuture() : Future[Connection] = {
future {
// how to remove blocking get and return a scala future?
connectionPool.getConnectionAsync().get(30000, TimeUnit.MILLISECONDS)
}
}
Idealmente, quiero una función de scala que devuelva la conexión como un futuro como el código anterior pero sin el bloqueo de código a través de la obtención. ¿Qué más necesito poner en la función para que no se bloquee?
Cualquier punto sería genial.
La biblioteca scala-java8-compat proporciona conversores entre java8 y Scala Futures.
Específicamente, puede usar FutureConverters.toScala(connectionPool.getConnectionAsync())
para convertir el java.util.concurrent.Future
a scala.concurrent.Future
import java.util.concurrent.{Future => JFuture}
import scala.concurrent.{Future => SFuture}
No puedes envolver JFuture
con SFuture
sin bloquear, ya que hay una devolución de llamada en SFuture
( onComplete
) y solo hay bloqueo para get
JFuture
.
Todo lo que puedes hacer es crear un hilo adicional y bloquearlo con get
, luego completar Promise
con el resultado de 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
Podrías comprobar isDone
en un bucle sin fin, pero no creo que sea mejor que bloquear.
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
}
}
Esto le permite al ExecutionContext saber que lo que está haciendo va a bloquear, lo que le da la oportunidad de asignar más subprocesos. Si no incluye el blocking { }
, puede quedarse sin hilos.