如何防止未来永远不会结束

时间:2019-06-12 03:47:33

标签: scala future

假设我有多个要并行运行的任务。

每个任务(方法)都有一个内部递归函数,该函数基本上从数据库中获取数据并将其保存在某些数据存储中。

[简化的内部递归函数]

 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出于某种原因永远不会完成。

[A]

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以使其按预期运行?

3 个答案:

答案 0 :(得分:2)

我无法重现您的问题,但是造成异常行为的原因可能是第一个示例中的语法不完全正确。您应该像这样写出第一个理解力:

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

但是理解力是按顺序工作的,在第一个示例中,期货并行运行的唯一原因是期货急于启动(“期货从现在开始” )。

如果要确保期货将并行执行,请使用Future.sequence

val f = Future.sequence(
  List(
    Future { someTask1() },
    Future { someTask2() },
    Future { someTask3() }
  )
)

答案 1 :(得分:0)

问题不在于理解,而在于您的任务。并行运行它们可能会导致某种死锁,但是我首先要三重检查它们是否不会陷入无限循环。查看您的示例,如果query.run.value从不返回空,然后递归将永远持续下去,则很容易发生这种情况。如果f1f2f3任何无法解析,那么f当然也不会解析。

答案 2 :(得分:0)

事实证明,在创建query对象时某些圆环引用导致了此问题。