фьючерсы начинают выполнять здесь:
val fFuture: Future[Int] = Future { println("f called"); 3 }
val gFuture: Future[Int] = Future { println("g called"); 4 }
Таким образом, обе казни начинают параллельно. Однако, если вы случайно положили Future{...}
внутрь для понимания, они будут исполняться последовательно.
Для понимания в основном подписывается и объединяет два результата в одно Будущее. Однако в вашем случае это похоже на то, что результат второго будущего был проигнорирован, что не имеет смысла. Код, который имеет смысл:
for {
f <- fFuture
g <- gFuture
} yield f + g
Этот код возвращает Future[Int]
(такой же, как код в вашем примере). Если вы извлечете ценность из этого будущего, вы получите 3 + 4 = 7
. Однако это еще не самый лучший подход, как ваши вычисления независимы и вероятность ошибки разработчика (указано выше), что делает их последовательным по-прежнему высок, поэтому рекомендуемый подход для независимых вычислений является:
(fFuture zip gFuture) map {
case (f, g) => f + g
}
Этот код референциально прозрачным это означает, что даже если заменить fFuture
с Future{...}
- он по-прежнему ведет себя так же (в случае Future
-Они будет выполнен в prallel, но это может быть различным для других параллельности примитивов)
Где бы for-comprehension
на самом деле имеет смысл ?Здесь:
for {
f <- Future{... 9}
g <- if (f > 0) Future{...} else Future{...}
} yield g
Как g
зависит от f
здесь - нет никакого способа, чтобы запустить те параллельно, так for
обеспечивает нелипкий способом составления несколько Future
сек
«Будущее» не выполняется внутри 'for'. Они выполняются, когда объявляются (всегда), и создаются с помощью 'for'. – cchantep
@cchantep Технически они выполняются только тогда, когда ExecutionContext решает их выполнить. –
Правильно, я должен был сказать, выполненный в свое время по решению ЕС, поскольку их объявления, возможно, (что важно там) между декларацией и перед 'for', без предсказуемого порядка, поскольку эти« Будущие »не зависят друг на друга. – cchantep