将 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