【问题标题】:Futures that flatMap a list of futures are doing a blocking operation, so why not enclose the code in blocking {..}?flatMap 期货列表的期货正在执行阻塞操作,那么为什么不将代码包含在阻塞 {..} 中呢?
【发布时间】:2015-11-08 20:07:01
【问题描述】:

在完成 Reactive Programming 上 Coursera 课程的一些练习和视频时,我看到了对期货的 List 进行“排序”的方法的定义。该方法返回一个Future,它将等待fts中的所有期货(参见下面的代码)并将这些结果打包到一个List[T]中,当序列返回的Future[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)))
    }
}

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

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

    blocking {
      Thread.sleep(1000)
    } 

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

现在...我不明白为什么“匹配”表达式没有包含在“阻塞”表达式中。难道我们不希望所有的 flatMapping (可能)花费大量时间吗?

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

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

【问题讨论】:

    标签: multithreading scala future blocking


    【解决方案1】:

    难道我们不希望所有的 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. 兑现承诺

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

    我认为这种描述有些误导。您从Future.sequence 返回的Future 并没有真正“工作”。正如您在上面的代码中看到的,您从flatMap 获得的Future(以及因此您从Future.sequence 获得的Future)只是一个最终将由其他东西完成的承诺。唯一真正做任何事情的是ExecutionContextFutures 只是指定要做什么。

    【讨论】:

      猜你喜欢
      • 2016-06-02
      • 2020-11-16
      • 2013-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-15
      • 2019-08-21
      • 2017-01-26
      相关资源
      最近更新 更多