通过Reactive Programming上的Coursera课程中的一些练习和视频,我看到了一种方法的定义,以期待未来的方法 . 该方法返回 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)))
}
}
这段代码是由教师给出的,所以我猜它应该代表如何做这种事情的最佳模式 . 然而,在讲座的其他地方,教师们说:
每当您有长时间运行的计算或阻塞时,请确保在阻塞构造内部运行它 . 例如:blocking {
了Thread.sleep(1000)
}
用于将一段代码指定为可能阻塞的代码 . 具有阻塞构造的异步计算通常在单独的线程中调度,以避免潜在的死锁 . 示例:假设您有一个等待计时器或资源或监视条件的未来f,这些条件只能由其他未来g来实现 . 在这种情况下,执行等待的f中的代码部分应该包含在阻塞中,否则将来可能永远不会运行g .
现在......我不明白为什么“匹配”表达式没有包含在“阻塞”表达式中 . 难道我们不希望所有flatMapping(可能)花费大量时间吗?
附注:scala.concurrent.Future类中有一个“官方”序列方法,该实现也不使用阻塞 .
我也会将它发布到Coursera论坛,如果我得到回复,我也会在这里发布 .
1 回答
不 .
flatMap
只是构造一个新的Future
并立即返回 . 它不会阻止 .见the default implementation of flatMap . 这是它的简化版本:
调用
flatMap
时会发生什么情况:创建承诺
为此未来添加回调
回报承诺
我认为这种描述有点误导 . 你从
Future.sequence
回来的Future
并不是真的"do work" . 正如你在上面的代码中看到的那样,你从flatMap
得到的Future
(以及你从Future.sequence
获得的Future
)只是一个最终将由其他东西完成的承诺 . 唯一真正做到的是ExecutionContext
;Future
只是指定要做什么 .