Вопрос:

Как предотвратить будущее никогда не заканчиваться

scala future

57 просмотра

3 ответа

922 Репутация автора

Предположим, у меня есть несколько задач, которые я хочу выполнять параллельно.

Каждая задача (метод) имеет внутреннюю рекурсивную функцию, которая в основном извлекает данные из базы данных и сохраняет их в некотором хранилище данных.

[упрощенная внутренняя рекурсивная функция]

 def simplifiedSomeTask(): Unit = {
    @scala.annotation.tailrec
    def get(
        stream: Stream[SomeEntity],
        result: Seq[SomeEntity],
    ): Stream[SomeEntity] = result match {
      case Nil =>
        stream
      case _ =>
        val query = //query to fetch data from database
        get(
          stream append result.toStream,
          query.run.value, // get fetched data from database
        )
    }

    val buffer = collection.mutable.Map.empty[String, String]

    get(
      Stream.empty,
      query.run.value
    ).foreach { r =>
      buffer.put(r.loginId, r.userId)
    }
  }

При попытке запустить A, Future никогда не заканчивается по какой-то причине.

[А]

val f1 =Future { someTask1() }
val f2 =Future { someTask2() }
val f3 =Future { someTask3() }

val f = for {
  _ <- f1 
  _ <- f2 
  _ <- f3 
} yield ()

Await.result(f, Duration.Inf)

Однако B работает (хотя он не работает параллельно)

[B]

val f = for {
  _ <- Future { someTask1() }
  _ <- Future { someTask2() }
  _ <- Future { someTask3() }
} yield ()

Await.result(f, Duration.Inf)

Как мне изменить A так, чтобы он работал как положено?

Автор: d-_-b Источник Размещён: 12.06.2019 03:47

Ответы (3)


2 плюса

9265 Репутация автора

Я не могу воспроизвести вашу проблему, но причина странного поведения может заключаться в том, что ваш синтаксис в первом примере не совсем правильный. Вы должны написать свой первый для понимания, как:

val f = for {
  _ <- f1
  _ <- f2
  _ <- f3
} yield ()

Но для понимания работает последовательно, и единственная причина, по которой ваши фьючерсы работают параллельно в вашем первом примере, заключается в том, что фьючерсы начинаются с нетерпением ( «Будущее начинается сейчас» ).

Если вы хотите убедиться, что Futures будет выполняться параллельно Future.sequence:

val f = Future.sequence(
  List(
    Future { someTask1() },
    Future { someTask2() },
    Future { someTask3() }
  )
)
Автор: Krzysztof Atłasik Размещён: 12.06.2019 04:58

0 плюса

181 Репутация автора

Проблема не в понимании, а в ваших задачах. Потенциально существует какой-то тупик от их параллельного запуска, но сначала я бы трижды проверил, что они не попадают в бесконечный цикл. Глядя на ваш пример, это может легко случиться, если query.run.valueникогда не вернется пустым, и тогда рекурсия продолжится навсегда. Если какой - либо из f1, f2и f3не решить, то fне будет, конечно , никогда не решить либо.

Автор: Henrik Размещён: 12.06.2019 04:53

0 плюса

922 Репутация автора

Решение

Оказалось, что некоторые ссылки окружности при создании queryобъектов вызывали эту проблему.

Автор: d-_-b Размещён: 27.06.2019 01:21
Вопросы из категории :
32x32