flatMap期货列表的期货正在进行阻止操作,那么为什么不将代码括在阻塞{...}中呢?

时间:2015-08-15 20:46:02

标签: multithreading scala future blocking

Reactive Programming上完成Coursera课程的一些练习和视频时,我看到了一种方法的定义,即'序列'List期货。该方法返回Future,它将执行等待fts中所有未来的工作(请参阅下面的代码),并将这些结果打包在List[T]中,Future[List[T]]将在{def sequence[T](fts: List[Future[T]]): Future[List[T]] = { fts match { case Nil => Future(Nil) case (ft::fts) => ft.flatMap(t => sequence(fts) .flatMap(ts => Future(t::ts))) } } 时可用序列返回的1}}已完成。

    blocking {
      Thread.sleep(1000)
    } 

这段代码是由教师给出的,所以我猜它应该代表如何做这种事情的最佳模式。然而,在讲座的其他地方,教师们说:

  

每当你有长时间运行的计算或阻塞时,请确保   在阻塞构造中运行它。例如:

CloudConfigurationManager
     

用于将一段代码指定为可能阻塞。具有阻塞构造的异步计算是   通常安排在一个单独的线程中,以避免潜在的死锁。   示例:假设您有一个等待计时器或等待的未来f   资源或监视条件,只能由某些人来履行   其他未来g。在那种情况下,f中的代码部分就是这样做的   等待应该在封锁中包裹,否则将来g   可能永远不会被运行。

现在......我不明白为什么'match'表达式没有包含在'blocking'表达式中。难道我们不希望所有flatMapping(可能)花费大量时间吗?

附注:scala.concurrent.Future类中有一个“官方”序列方法,该实现也不使用阻塞。

我也会将它发布到Coursera论坛,如果我得到回复,我也会在这里发帖。

1 个答案:

答案 0 :(得分:4)

  

难道我们不希望所有flatMapping都(可能)花费大量时间吗?

不。 flatMap只构建一个新的Future并立即返回。它不会阻止。

the default implementation of flatMap。这是它的简化版本:

trait Future[+T] {

  def flatMap[S](f: T => Future[S])
                (implicit executor: ExecutionContext): Future[S] = {

    val promise = new Promise[S]()

    this.onComplete {

      // The first Future (this) failed
      case Failure(t) => promise.failure(t)

      case Success(v1) =>

        // Apply the flatMap function (f) to the first Future's result
        Try(f(v1)) match {

          // The flatMap function (f) threw an exception
          case Failure(t) => promise.failure(t)

          case Success(future2) =>
            future2.onComplete {

              // The second Future failed
              case Failure(t) => promise.failure(t)

              // Both futures succeeded - Complete the promise
              // successfully with the second Future's result.
              case Success(v2) => promise.success(v2)
            }
        }
    }
    promise.future
  }
}

致电flatMap时会发生什么情况:

  1. 创建承诺
  2. 为此未来添加回调
  3. 退还承诺
  4.   

    该方法返回Future,它将完成等待所有期货的工作

    我认为这种描述有些误导。您从Future返回的Future.sequence并没有“真正起作用”。正如您在上面的代码中看到的那样,您从Future获得的flatMap(以及您从Future获得的Future.sequence只是一个最终将完成的承诺通过别的东西。唯一真正做到的是ExecutionContext; Future只是指定要做什么。