scala.concurrent.Future wrapper for java.util.concurrent.Future

旧城冷巷雨未停 提交于 2019-11-26 21:09:30

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!