将 Java Future 转换为 Scala Future
Convert a Java Future to a Scala Future
我有一个 Java Future
对象,我想将其转换为 Scala Future
。
看看 j.u.c.Future
API,除了 isDone
方法,我没有什么可以使用的。这是isDone
方法阻塞吗?
目前我的想法是这样的:
val p = Promise()
if (javaFuture.isDone())
p.success(javaFuture.get)
有更好的方法吗?
如何包装它(我假设这里有一个隐式的 ExecutionContext):
val scalaFuture = Future {
javaFuture.get
}
编辑:
一个简单的轮询策略可能如下所示 (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))
这将检查 Java 未来是否每 500 毫秒完成一次。显然总阻塞时间与上面相同(四舍五入到最接近的 500 毫秒)但是这个解决方案将允许其他任务在 ExecutionContext
.
的同一线程中交错
使用 FutureConvertors(Scala 中的内置实用程序)将 Java Future 转换为 Scala Future。
考虑将 Java Future[Int] 转换为 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
}))
我们可以为任何自定义类型而不是 Int 做类似的事情。
从 Scala 2.13
开始,标准库包括 scala.jdk.FutureConverters
,它向 Scala CompletableFuture/Future
提供 Java 隐式转换:
import scala.jdk.FutureConverters._
// val javaFuture = java.util.concurrent.CompletableFuture.completedFuture(12)
val scalaFuture = javaFuture.asScala
// scalaFuture: scala.concurrent.Future[Int] = Future(Success(12))
对于现在阅读此问题的人,如果您使用的是 Scala 2.13 及更高版本,请使用:
import scala.jdk.FutureConverters._
并使用 completableFuture.asScala
进行转换
如果您使用的是 Scala 2.12 及更低版本,请使用
import scala.compat.java8.FutureConverters._
并使用以下方式转换:toScala(completableFuture)
或 completableFuture.toScala
此外,在 Scala 2.12 中确保您使用的是正确的工件:
org.scala-lang.modules:scala-java8-compat_2.12:0.9.0
现在,如果出于某种原因您拥有的实际上是 Future
而不是 CompletableFuture
,这在当今应该是很少见的情况,请遵循其中第一个答案:Transform Java Future into a CompletableFuture
我有一个 Java Future
对象,我想将其转换为 Scala Future
。
看看 j.u.c.Future
API,除了 isDone
方法,我没有什么可以使用的。这是isDone
方法阻塞吗?
目前我的想法是这样的:
val p = Promise()
if (javaFuture.isDone())
p.success(javaFuture.get)
有更好的方法吗?
如何包装它(我假设这里有一个隐式的 ExecutionContext):
val scalaFuture = Future {
javaFuture.get
}
编辑:
一个简单的轮询策略可能如下所示 (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))
这将检查 Java 未来是否每 500 毫秒完成一次。显然总阻塞时间与上面相同(四舍五入到最接近的 500 毫秒)但是这个解决方案将允许其他任务在 ExecutionContext
.
使用 FutureConvertors(Scala 中的内置实用程序)将 Java Future 转换为 Scala Future。
考虑将 Java Future[Int] 转换为 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
}))
我们可以为任何自定义类型而不是 Int 做类似的事情。
从 Scala 2.13
开始,标准库包括 scala.jdk.FutureConverters
,它向 Scala CompletableFuture/Future
提供 Java 隐式转换:
import scala.jdk.FutureConverters._
// val javaFuture = java.util.concurrent.CompletableFuture.completedFuture(12)
val scalaFuture = javaFuture.asScala
// scalaFuture: scala.concurrent.Future[Int] = Future(Success(12))
对于现在阅读此问题的人,如果您使用的是 Scala 2.13 及更高版本,请使用:
import scala.jdk.FutureConverters._
并使用 completableFuture.asScala
如果您使用的是 Scala 2.12 及更低版本,请使用
import scala.compat.java8.FutureConverters._
并使用以下方式转换:toScala(completableFuture)
或 completableFuture.toScala
此外,在 Scala 2.12 中确保您使用的是正确的工件:
org.scala-lang.modules:scala-java8-compat_2.12:0.9.0
现在,如果出于某种原因您拥有的实际上是 Future
而不是 CompletableFuture
,这在当今应该是很少见的情况,请遵循其中第一个答案:Transform Java Future into a CompletableFuture