首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >未来/成功竞赛

未来/成功竞赛
EN

Stack Overflow用户
提问于 2013-12-18 21:23:33
回答 3查看 2.2K关注 0票数 7

我正在学习期货,并且我正在尝试创建一个方法,该方法以两个期货(fg)为参数,并返回第一个成功完成的未来,否则返回fg

下面是一些用例来说明我的方法的行为:

代码语言:javascript
复制
Future 1        | Future 2         | Result
Success First     Success Second     Future 1
Success First     Failure Second     Future 1
Success Second    Success First      Future 2
Success Second    Failure First      Future 1
Failure First     Failure Second     Future 2 (because we had a failure on Future 1, so try to see what is the result Future 2)

所以我创建了这个方法:

代码语言:javascript
复制
def successRace(f: Future[T], g: Future[T]): Future[T] = {
        val p1 = Promise[T]()
        val p2 = Promise[T]()
        val p3 = Promise[T]()
        p1.completeWith(f)
        p2.completeWith(g)
        p3. ????
        p3.future
}

现在,我怎么知道哪一个先完成了?

EN

回答 3

Stack Overflow用户

发布于 2013-12-19 02:07:58

用例是第一次成功完成:

代码语言:javascript
复制
scala> :pa
// Entering paste mode (ctrl-D to finish)

def firstSuccessOf[T](fs: Future[T]*)(implicit x: ExecutionContext): Future[T] = {
  val p = Promise[T]()
  val count = new java.util.concurrent.atomic.AtomicInteger(fs.size)
  def bad() = if (count.decrementAndGet == 0) { p tryComplete new Failure(new RuntimeException("All bad")) }
  val completeFirst: Try[T] => Unit = p tryComplete _
  fs foreach { _ onComplete { case v @ Success(_) => completeFirst(v) case _ => bad() }}
  p.future
}

// Exiting paste mode, now interpreting.

firstSuccessOf: [T](fs: scala.concurrent.Future[T]*)(implicit x: scala.concurrent.ExecutionContext)scala.concurrent.Future[T]

所以

代码语言:javascript
复制
scala> def f = Future { Thread sleep 5000L ; println("Failing") ; throw new NullPointerException }
f: scala.concurrent.Future[Nothing]

scala> def g = Future { Thread sleep 10000L ; println("OK") ; 7 }
g: scala.concurrent.Future[Int]

scala> firstSuccessOf(f,g)
res3: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@5ed53f6b

scala> res0Failing
          3.value
res4: Option[scala.util.Try[Int]] = None

scala> res3.valueOK

res5: Option[scala.util.Try[Int]] = Some(Success(7))

代码语言:javascript
复制
scala> def h = Future { Thread sleep 7000L ; println("Failing too") ; throw new NullPointerException }
h: scala.concurrent.Future[Nothing]


scala> firstSuccessOf(f,h)
res10: scala.concurrent.Future[Nothing] = scala.concurrent.impl.Promise$DefaultPromise@318d30be

scala> 

scala> res10.Failing
value
res11: Option[scala.util.Try[Nothing]] = None

scala> Failing too


scala> res10.value
res12: Option[scala.util.Try[Nothing]] = Some(Failure(java.lang.RuntimeException: All bad))

@ ysusuk的答案是Future.firstCompletedOf在幕后做了什么。

票数 5
EN

Stack Overflow用户

发布于 2013-12-18 22:50:56

您希望使用tryCompleteWith方法。它可以被调用多次,并且只有第一次完成以后才会成功。

代码语言:javascript
复制
def successRace(f: Future[T], g: Future[T]): Future[T] = {
  val p = Promise[T]()
  p.tryCompleteWith(f)
  p.tryCompleteWith(g)
  p.future
}
票数 2
EN

Stack Overflow用户

发布于 2013-12-18 23:56:51

我完全同意前面的答案,但我希望我的例子能进一步澄清它,所以:

代码语言:javascript
复制
def successRace[T](f: Future[T], g: Future[T]): Future[T] = {
  val promise = Promise[T]()

  f onComplete(promise.tryComplete(_))
  g onComplete(promise.tryComplete(_))

  promise.future
}

因此,第一个完成的Future将设置包装在Try中的值(so、SuccessFailure)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20659406

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档