繁体   English   中英

来自CompletableFuture的whenComplete的签名

[英]Signature of whenComplete from CompletableFuture

有人知道将Java CompletableFuturewhenComplete方法转换为Scala吗? 我真的不知道该怎么做,我有点卡住了。 谢谢

这是一个示例,向您展示它如何工作(在scala REPL内部)...

$ scala
Welcome to Scala 2.12.6 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_181).
Type in expressions for evaluation. Or try :help.

scala> import java.util.concurrent.CompletableFuture
import java.util.concurrent.CompletableFuture

创建一个等待5秒钟的future,然后完成返回一个字符串值。 (另请参见下面的注释,说明其工作原理。)

scala> val future = CompletableFuture.supplyAsync {() =>
     |   Thread.sleep(5000) // Wait 5,000 ms (5 seconds).
     |   "We done did it!"
     | }
future: java.util.concurrent.CompletableFuture[String] = java.util.concurrent.CompletableFuture@5a466dd[Not completed]

现在,当将来完成时,将执行一些代码。 (这是您应该从自己的whenComplete实现开始的whenComplete 。)

scala> future.whenComplete {(result, error) =>
     |   println(s"Result was: '$result', error was: '$error'")
     | }
Result was 'We done did it!'; error was 'null'
res0: java.util.concurrent.CompletableFuture[String] = java.util.concurrent.CompletableFuture@3ea9a091[Completed normally]

(请注意,在这种情况下,将来会在我能够键入whenComplete方法之前完成。这显然是一个竞争条件,因此,如果将全部全部一次粘贴到REPL中,则可能会发现res0已确定为具有“未完成”,然后查看whenComplete函数的输出。)

那么,这是怎么回事,因为此代码看起来与关联类的JavaDoc不太相似?

这是一种Scala魔术,称为单一抽象方法 本质上,如果一个抽象类(或特征)具有单个抽象方法,则可以用该抽象方法的定义替换该类的实例。 此外, Scala从关联函数的参数列表中知道哪个类是相关的。

让我们从CompletableFuture.supplyAsync开始,它采用一个Supplier[T]参数。 Scala术语来说,这种类型如下:

trait Supplier[T] {
  def get(): T
}

因此,我们可以这样编写future元素的创建,如下所示:

scala> import java.util.function.Supplier
import java.util.function.Supplier

scala> val future = CompletableFuture.supplyAsync {
     |   new Supplier[String] {
     |     override def get(): String = {
     |       Thread.sleep(5000) // Wait 5,000 ms (5 seconds).
     |       "We done did it!"
     |     }
     |   }
     | }
future: java.util.concurrent.CompletableFuture[String] = java.util.concurrent.CompletableFuture@35becbd4[Not completed]

因为Scala编译器知道supplyAsync接受了Supplier[T] ,并且因为Supplier[T]具有单个抽象方法 get ,所以编译器能够接受使用功能文字作为Supplier及其定义的缩写形式。 get方法。

然后,我们对whenComplete方法使用相同的方法。 在这里,参数的类型是BiConsumer[T, U] (其中TBiConsumer[T, U]返回的值的类型,而U是异常类型),它采用单个抽象方法 accept (此类型也具有andThen方法,但这不是抽象方法,因此对Scala而言无关紧要。)因此,为了更加明确,我们可以编写以下代码:

scala> import java.util.function.BiConsumer

scala> future.whenComplete {
     |   new BiConsumer[String, Throwable] {
     |     override def accept(result: String, error: Throwable): Unit = {
     |       println(s"Result was: '$result', error was: '$error'")
     |     }
     |   }
     | }
Result was 'We done did it!'; error was 'null'
res0: java.util.concurrent.CompletableFuture[String] = java.util.concurrent.CompletableFuture@3ea9a091[Completed normally]

两种方法都是有效的,因此请随意使用对您有意义的任何一种方法。

需要注意的是whenComplete比传统的Scala代码丑陋了很多通常需要:如果未来抛出一个异常而不是成功完成,那么error将非null ; 否则, result将包含将来的结果,也可以为null

如果有可能,我强烈建议您改用Scala Future Java中的功能更强大,更优雅。

您可以通过以下隐式转换将Java CompletableFuture转换为Scala Future

import scala.concurrent.{Future, Promise}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.language.implicitConversion
import scala.util.{Failure, Success}

implicit def completableFutureToFuture[T](cf: CompletableFuture[T]): Future[T] = {
  val p = Promise[T]() // Promise monitoring result of java cf.

  // Handle completion of Java future.
  cf.whenComplete {(result, error) =>

    // If error is not null, then future failed.
    if(error ne null) p.failure(error)

    // Otherwise, it succeeded with result.
    else p.success(result)
  }

  // Return the Scala future associated with the promise.
  p.future
}

然后,您可以更加优雅地处理Java未来的完成(同样,在REPL中,使用上面的定义):

scala> val scalaFuture = future // Implicit conversion called.
scalaFuture: scala.concurrent.Future[String] = Future(Success(We done did it!))

scala> scalaF.onComplete {
     |   case Success(s) => println(s"Succeeded with '$s'")
     |   case Failure(e) => println(s"Failed with '$e'...")
     | }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM