2013-12-18 6 views
4

Я изучаю будущее, и я пытаюсь создать метод, который, взять два фьючерсные как параметр (f и g) и вернуть первое будущее, который был успешно завершен, в противном случае она возвращает f или g.Futures/Успех гонка

В некоторых случаях используют для иллюстрации поведения моего метода:

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) 

Так что я создал этот метод:

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 
} 

А теперь, как я могу знать, какой из них завершен первый?

ответ

2

Вы хотите использовать метод tryCompleteWith. Его можно назвать несколько раз, и побеждает только первое завершение будущего.

def successRace(f: Future[T], g: Future[T]): Future[T] = { 
    val p = Promise[T]() 
    p.tryCompleteWith(f) 
    p.tryCompleteWith(g) 
    p.future 
} 
+3

Вы видите это, пожалуйста? http://pastebin.com/2yqDHN5t. С тем, что я описываю, он должен вернуть будущее g, потому что будущий f терпит неудачу, с помощью вашего метода он пытается выполнить обещание с будущим, которое завершается первым, но на него не волнует, если он потерпел неудачу или нет. – user2336315

+0

Ответ не соответствует вопросу –

1

Я полностью согласен с предыдущим ответом, еще я надеюсь, что мой пример пояснит это немного дальше, так:

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 (так , Success или Failure).

+2

Как я уже сказал в комментарии выше, ваша реализация попыталась выполнить обещание, но это не волнует, если это неудача или нет. См. Pastebin в других комментариях. – user2336315

+0

@ user2336315 вы определенно правы, эта реализация не волнует, что является результатом первого завершенного «Будущего» («Успех» или «Сбой»). – iuriisusuk

3

Прецедент является первым успешным завершением:

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] 

так

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] = [email protected] 

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

scala> res3.valueOK 

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

или

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] = [email protected] 

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 «s ответ, что Future.firstCompletedOf делает под капотом.

Смежные вопросы