Scala.concurrent.Future обертка для java.util.concurrent.Future
Я использую Play Framework 2.1.1 с внешней java-библиотекой, которая создает файл java.util.concurrent.Future. Я использую будущее scala, а не 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. Что еще мне нужно, чтобы включить функцию, чтобы она не блокировалась.
Любые указатели будут замечательными.
Ответы
Ответ 1
import java.util.concurrent.{Future => JFuture}
import scala.concurrent.{Future => SFuture}
Вы не можете обернуть JFuture
с SFuture
без блокировки, так как есть обратный вызов в SFuture
(onComplete
) и блокируется только get
в JFuture
.
Все, что вы можете сделать, это создать дополнительный поток и заблокировать его с помощью get
, а затем завершить Promise
с результатом 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
Вы можете проверить isDone
в бесконечном цикле, но я не думаю, что лучше блокировать.
Ответ 2
Future {
blocking {
jfuture.get
}
}
Это позволяет ExecutionContext знать, что то, что вы делаете, блокируется, предоставляя ему возможность выделять больше потоков. Если вы не включили blocking { }
, тогда у вас может закончиться поток.
Ответ 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
Библиотека scala-java8-compat предоставляет преобразователи между java8 и Scala Futures.
В частности, вы можете использовать FutureConverters.toScala(connectionPool.getConnectionAsync())
для преобразования java.util.concurrent.Future
в scala.concurrent.Future