Как дождаться результата Scala Futures в понимании

У меня проблема с приведенным ниже фрагментом кода. Я хочу, чтобы метод «комбинирования» запускался после завершения всех методов «молотый кофе», «нагреватель воды, вспененное молоко». Они будут запускаться одновременно. Все 4 метода измельчения, нагрева воды, вспенивания молока и пивоварения одновременно выполняются с использованием future.

def prepareCappuccino(): Future[Cappuccino] = {
  val groundCoffee = grind("arabica beans")
  val heatedWater = heatWater(Water(20))
  val frothedMilk = frothMilk("milk")
  for {
    ground <- groundCoffee
    water <- heatedWater
    foam <- frothedMilk
    espresso <- brew(ground, water)
  } yield combine(espresso, foam)
}

Когда я выполняю вышеуказанный метод, я получаю ниже

start grinding...
heating the water now
milk frothing system engaged!

И после этого программа выходит. Я получил этот пример с сайта, когда пытался изучить фьючерсы. Как можно заставить программу ждать, чтобы метод объединения сработал после того, как все фьючерсы вернутся?


person mavrav    schedule 19.05.2014    source источник
comment
Спасибо @ om-nom-nom за помощь с форматированием   -  person mavrav    schedule 19.05.2014
comment
Вы можете просто ввести Thread.sleep (duration) или использовать Await из пакета scala.concurrent   -  person goral    schedule 19.05.2014
comment
да, я могу это сделать. Когда я использую точку останова, программа завершается, как ожидалось. Но я не этого хочу. Есть ли другой способ сделать это, когда выполнение метода комбинирования происходит без выхода из программы? Надеюсь, я не слишком запутываю   -  person mavrav    schedule 19.05.2014
comment
Я только что дал вам решение. import scala.concurrent.duration._ scala.concurrent.Await.ready(prepareCappuccino, 5.seconds)   -  person goral    schedule 19.05.2014


Ответы (2)


Вы можете использовать Await здесь:

val f = Future.sequence(futures.toList)
Await.ready(f, Duration.Inf)

Я полагаю, у вас есть список всех фьючерсов. Await.ready выполняет всю работу по ожиданию.

person codejitsu    schedule 19.05.2014
comment
Я сделал это, и это сработало. Но функция onSuccess отдельных фьючерсов не запускается. Есть способ сделать это? - person mavrav; 19.05.2014
comment
@mavrav, если вы используете map вместо onSuccess и Await в результате future, вы получите желаемое поведение. - person Aivean; 29.04.2016

Решение, уже опубликованное в Await на будущее, является решением, если вы хотите намеренно заблокировать выполнение в этом потоке. Две распространенные причины для этого - это тестирование, когда вы хотите дождаться результата, прежде чем делать утверждение, и когда в противном случае все потоки завершились бы (как в случае с игрушечными примерами).

Однако в надлежащем долгоживущем приложении Await обычно следует избегать.

В вашем вопросе уже есть один из правильных способов сделать будущую композицию - использовать для понимания. Имейте в виду, что for-compольсии преобразуются в операции flatMaps, maps и withFilter, поэтому любые фьючерсы, которые вы вызываете в for-complation, будут созданы только после завершения других, то есть последовательно.

Если вы хотите, чтобы несколько фьючерсов работали одновременно, вы должны создать их, прежде чем вводить for-computing, как вы это сделали.

person sksamuel    schedule 19.05.2014
comment
Правильно, @monkjack. Но когда я пытаюсь запустить этот пример, метод комбинирования никогда не вызывается, чего я не хочу. На самом деле я имитирую это, чтобы соответствовать системе загрузки кеша во время запуска сервера, где кеши должны загружаться одновременно, чтобы сэкономить время, поэтому, если входящий поток приходит во время загрузки кеша, он должен дождаться загрузки объектов кеша. Поэтому я считаю, что Await.ready - хороший способ реализовать это. Поправьте меня, если я ошибаюсь - person mavrav; 19.05.2014
comment
Ситуация, с которой вы столкнулись, вероятно, связана с завершением вашей программы. Что касается хорошего решения вашей проблемы, которая заключается в задержке запросов до достижения состояния, опубликуйте еще один вопрос с конкретными деталями. - person sksamuel; 19.05.2014