I have a Java Future
object which I would like to convert into a Scala Future
.
Looking at the j.u.c.Future
API, there is nothing much that I could use other than the isDone
method. Is this isDone
method blocking?
Currently this is what I have in my mind:
val p = Promise()
if (javaFuture.isDone())
p.success(javaFuture.get)
Is there a better way to do this?
How about just wrapping it (I'm assuming there's an implicit ExecutionContext here):
val scalaFuture = Future {
javaFuture.get
}
EDIT:
A simple polling strategy could look like this (java.util.Future => F):
def pollForResult[T](f: F[T]): Future[T] = Future {
Thread.sleep(500)
f
}.flatMap(f => if (f.isDone) Future { f.get } else pollForResult(f))
This will check if the Java future is done every 500ms. Obviously the total blocking time is the same as above (rounded up to the nearest 500ms) but this solution will allow other tasks to be interleaved in the same thread of the ExecutionContext
.
Starting Scala 2.13
, the standard library includes scala.jdk.FutureConverters
which provides Java to Scala CompletableFuture/Future
implicit conversions:
import scala.jdk.FutureConverters._
// val javaFuture = java.util.concurrent.CompletableFuture.completedFuture(12)
val scalaFuture = javaFuture.asScala
// scalaFuture: scala.concurrent.Future[Int] = Future(Success(12))
Use FutureConvertors (built-in util in Scala) for conversion of Java Future to Scala Future.
Consider an example for converting Java Future[Int] to Scala Future[Int] ::
import java.util.concurrent.CompletableFuture
import scala.compat.java8.FutureConverters
val javaFuture: java.util.concurrent.Future[Int] = ???
// Some method call which returns Java's Future[Int]
val scalaFuture: Future[Int] =
FutureConverters.toScala(CompletableFuture.supplyAsync(new Supplier[Int] {
override def get(): Int = javaFuture.get
}))
Similar we can do for any custom type instead of Int.
For those reading this question now, if you're using Scala 2.13 and above, use:
import scala.jdk.FutureConverters._
And convert using completableFuture.asScala
If you're using Scala 2.12 and below, use
import scala.compat.java8.FutureConverters
And convert using: toScala(completableFuture)
or completableFuture.toScala
Also, in Scala 2.12 make sure you're using the correct artifact:
org.scala-lang.modules:scala-java8-compat_2.12:0.9.0
来源:https://stackoverflow.com/questions/35033290/convert-a-java-future-to-a-scala-future