给出以下两种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
?
答案 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]]
,这在这种情况下有意义(因为结果总是false
或true
),您可以轻松使用map
:
val anyPositive = firstPositiveNumber map (_.isDefined)
val result = Await.result(anyPositive, 3.seconds)
println(result)
您可以在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")