Play Framework2.1.1を外部のJavaライブラリでJava.util.concurrent.Futureの結果を生成します。scala Play 2.1の時点で行うのが正しいと思うAkkaとは対照的に、futureです。コードをブロックしないまま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)
}
}
理想的には、上記のコードのように未来として接続を返すが、getを介してコードをブロックしない、scala関数が必要です。ブロックしないようにするには、他に何を関数に入れる必要がありますか? 。
どんなポインタも素晴らしいでしょう。
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
をチェックすることはできますが、ブロックするよりも良いとは思いません。
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
に変換できます。