在Scala文档中,有一个示例如何选择未来通过承诺更快地成功的示例。
http://docs.scala-lang.org/overviews/core/futures.html#promises
def first[T](f: Future[T], g: Future[T]): Future[T] = {
val p = promise[T]
f onSuccess {
case x => p.trySuccess(x)
}
g onSuccess {
case x => p.trySuccess(x)
}
p.future
}
此功能返回未来成功的未来,如果其中任何一个都失败了,则永远不会完成。
是否可以以某种方式对此进行修改,即使其他未来失败了,第二个是成功的,并且两个都成功了,那么越来越较快的速度就会像现在一样挑选。
您可以添加此:
f onFailure {
case e =>
g onFailure {
case _ =>
p.failure(e)
}
}
两个期货失败时,这将使承诺失败,而异常与f
相同。您可以对此进行详细说明,以创建一个例外,该异常记录了来自f
和g
的2个异常。
我建议您遵循Alvin Alexander在Scala中的期货和承诺的建议
我相信这是与期货合作的最佳方法
package futures
import scala.concurrent.{Future => ConcurrentTask} // rename
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}
import Utils.sleep
object FutureAsConcurrentTask extends App {
// run some long-running task (task has type Future[Int] in this example)
val task = ConcurrentTask {
Cloud.executeLongRunningTask
}
// whenever the task completes, execute this code
task.onComplete {
case Success(value) => println(s"Got the callback, value = $value")
case Failure(e) => println(s"D'oh! The task failed: ${e.getMessage}")
}
// do your other work
println("A ..."); sleep(100)
println("B ..."); sleep(100)
println("C ..."); sleep(100)
println("D ..."); sleep(100)
println("E ..."); sleep(100)
println("F ..."); sleep(100)
}
这是选择最快的未来的基本模式,如果它们都太慢了:
:import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{ Success, Failure }
import akka.actor._
import akka.pattern.after
object GetFastestFutureOrTimeout extends App {
val e = new TimeoutException("TimeoutException")
val system = ActorSystem("GetFastestFutureOrTimeout")
val f1 = Future { Thread.sleep(200); "this is f1" }
val f2 = Future { Thread.sleep(100); "this is f2" }
val timeoutFuture = after(500.milliseconds, using = system.scheduler) { Future.failed(e) }
val f = Future.firstCompletedOf(f1 :: f2 :: timeoutFuture :: Nil)
f onComplete {
case Success(msg) => println(msg)
case Failure(err) => println("An error occured: " + err.getMessage)
}
}
此打印"这是F2"。如果TimeOutFuture的超时更改为50,则将打印"发生错误:TimeOutException"。
在引擎盖下,FirstCompletedOf使用承诺返回完成的第一个未来的价值,请访问https://github.com/scala/scala/scala/blob/v2.11.6/src/library/scala/scala/scala/concurrent/concurrent/future/future/future.scala#l503。
这是一个基本的实现,以获取最快的成功响应,或者如果他们都失败了:
:def getFirstSuccessfulResultOrFail[T](requests: List[Future[T]]): Future[T] = {
val p = Promise[T]()
val countDownLatch = AtomicInt(0)
requests.foreach { f =>
f.onComplete {
case Failure(e) => if (countDownLatch.addAndGet(1) == requests.size) p.tryFailure(e)
case Success(s) => p.trySuccess(s)
}
}
p.future
}