评估具有单独完成时间的两个期货

时间:2015-02-27 02:04:24

标签: scala future

给出以下两种Future[Int]类型的方法:

scala> import scala.concurrent._
import scala.concurrent._

scala> import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.ExecutionContext.Implicits.global

scala> def g: Future[Int] = Future { Thread.sleep(5000); 100 }
g: scala.concurrent.Future[Int]

scala> def f: Future[Int] = Future { Thread.sleep(50000); 100 }
f: scala.concurrent.Future[Int]

如果未来的值大于0,我想返回Future[Boolean]

请注意,一个Future在50秒内完成,而另一个在5秒内完成。

scala> def foo: Future[Boolean] = for {
     |   x <- f
     |   y <- g
     | } yield ( (x > 0) || (y > 0) )
foo: scala.concurrent.Future[Boolean]

scala> Await.result(foo, 20 second)
warning: there were 1 feature warning(s); re-run with -feature for details
java.util.concurrent.TimeoutException: Futures timed out after [20 seconds]
    at scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:219)

当我运行它时,我会观察超时,因为我认为是50秒的未来。

一旦未来完成,是否可以重新编写foo以返回true

3 个答案:

答案 0 :(得分:0)

没有使用它们,但Future object methods中有一些好的候选人:

Future.firstCompletedOf返回列表中第一个未来结果的新Future。

Future.reduce在所提供的期货上开始折叠,其中fold-zero是首先完成的Future的结果值。

答案 1 :(得分:0)

简答

使用以下代码

  val firstPositiveNumber = Future.find(Seq(g, f))(_ > 0)
  val maybeResult = Await.result(firstPositiveNumber, 3 seconds)
  println(maybeResult.isDefined)

详细答案

find实用程序

实现此要求的最简单方法是使用Future随播对象中的find实用程序,这是一个常见的用例。

假设你有两个像这样定义的期货

import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global

  val g = Future {
    Thread.sleep(4000)
    100
  }

  val f = Future {
    Thread.sleep(2000)
    -100
  }

您可以使用find

val firstPositiveNumber = Future.find(Seq(g, f))(it => it > 0)

创建一个未来,当至少有一个提供的期货成功完成并且结果通过提供的条件时,将完成。如果所有期货都失败,结果将是Failure

请注意,结果未来的类型是Future[Option[Int]],这是有道理的,因为一些期货可能会成功,而他们的结果都不会满足条件。在这种情况下,结果将是None(当然包裹在Success中,因为未来本身就是成功的。)

未来的类型

如果您坚持要返回Future[Boolean]而不是Future[Option[Int]],这在这种情况下有意义(因为结果总是falsetrue),您可以轻松使用map

val anyPositive = firstPositiveNumber map (_.isDefined)
val result = Await.result(anyPositive, 3.seconds)
println(result)

Scala API

您可以在Scala API

中详细了解Future中的所有实用工具(合并期货,过滤它们等)

答案 2 :(得分:0)

如果您的期货收到不同的结果,您可以使用Future.firstCompletedOf。您的示例都返回相同的int,但您可以始终map为它们提供一些不同的标识,在本例中为Either,如下所示:

val f1: Either[Int,Int] = f().map(Left(_))
val g1: Either[Int,Int] = g().map(Right(_))
val futureOfFirst = Future.firstCompledOf(Seq(f1,g1)).map {
  case Left(x) => x
  case Right(x) => x
}
val first = Await.result(futureOfFirst, 20 seconds)
println(s"first result: $first")