Когда использовать Scala Futures? - PullRequest
0 голосов
/ 19 сентября 2019

Я искатель Scala Programmer.У меня блестящая работа, у которой есть подзадачи, которые нужно выполнить всю работу.Я хотел использовать Futures для параллельного выполнения подзадач.После завершения всей работы я должен вернуть ответ всей работы.

Что я слышал о scala Futures: как только основной поток будет выполнен и остановлен, остальные потоки будут уничтожены, а также вы получите пустой ответ.

Я должен использовать Await.result для сбора результатов.Но все блоги говорят, что вы должны избегать Await.result, и это плохая практика.

Использует ли Await.result верный способ или нет в mycase.?

def computeParallel(): Future[String] = {
  val f1 = Future {  "ss" }
  val f2 = Future { "sss" }
  val f3 = Future { "ssss" }

  for {
    r1 <- f1
    r2 <- f2
    r3 <- f3
  } yield (r1 + r2 + r3)
} 

computeParallel().map(result => ???)



Насколько я понимаю, мы должны использовать Futures в приложении типа Webservice, в котором всегда запущен один процесс, который не будет завершен.Но в моем случае, когда логическое выполнение (программа Scala) завершится, оно завершится.

Могу ли я использовать Futures для своей проблемы или нет.?

Заранее спасибо

1 Ответ

0 голосов
/ 19 сентября 2019

Использование futures в Spark, вероятно, не рекомендуется, за исключением особых случаев, и простое распараллеливание вычислений не входит в их число (вполне возможно, что для блокировки ввода-вывода (например, для выполнения запросов к стороннему сервису) используется неблокирующая оболочка).единственный особый случай).

Обратите внимание, что Future не гарантирует параллелизм (зависит от того, как и как они выполняются параллельно, зависит от ExecutionContext, в котором они выполняются), только асинхронность.Кроме того, в случае, если вы порождаете выполняющее вычисления будущее в преобразовании Spark (т. Е. На исполнителе, а не на драйвере), есть вероятность, что улучшения производительности не будет, так как Spark обычно выполняет хорошую работуподдерживая занятость ядер на исполнителях, все, что порождает эти фьючерсы, борется за ядра со Spark.

В общем, будьте очень внимательны при объединении абстракций параллелизма, таких как Spark RDD / DStreams / Dataframes, актеры и фьючерсы: естьмножество потенциальных минных полей, где такие комбинации могут нарушать гарантии и / или соглашения в различных компонентах.

Стоит также отметить, что у Spark есть требования в отношении сериализуемости промежуточных значений и что фьючерсы, как правило, не сериализуемы, поэтомуСтадия искры не может привести к будущему;это означает, что в принципе у вас нет выбора, кроме Await для фьючерсов, порожденных на стадии.

Если вы все еще хотите порождать фьючерсы на стадии Spark (например, отправлять их в веб-службу), возможно, этоЛучше всего использовать Future.sequence, чтобы свернуть фьючерсы в один, а затем Await на этом (обратите внимание, что я не проверял эту идею: я предполагаю, что существует неявное CanBuildFrom[Iterator[Future[String]], String, Future[String]] доступное):

def postString(s: String): Future[Unit] = ???

def postStringRDD(rdd: RDD[String]): RDD[String] = {
  rdd.mapPartitions { strings =>
    // since this is only get used for combining the futures in the Await, it's probably OK to use the implicit global execution context here
    implicit val ectx = ???
    Await.result(strings.map(postString))
  }
  rdd  // Pass through the original RDD
}
...