Multithreading flatMap一个期货列表的期货正在执行一个阻塞操作,那么为什么不将代码包含在阻塞{..}中呢?
在学习上Coursera课程的一些练习和视频时,我看到了一个方法的定义,即“排序”未来的Multithreading flatMap一个期货列表的期货正在执行一个阻塞操作,那么为什么不将代码包含在阻塞{..}中呢?,multithreading,scala,future,blocking,Multithreading,Scala,Future,Blocking,在学习上Coursera课程的一些练习和视频时,我看到了一个方法的定义,即“排序”未来的列表。该方法返回一个Future,它将在fts中等待所有期货(见下面的代码),并将这些结果打包到列表[T]中,当按顺序返回的Future[T]完成时,该列表将可用 def sequence[T](fts: List[Future[T]]): Future[List[T]] = { fts match { case Nil => Future(Nil) case (
列表。该方法返回一个Future
,它将在fts
中等待所有期货(见下面的代码),并将这些结果打包到列表[T]
中,当按顺序返回的Future[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
可能永远不会运行
现在。。。我不明白的是为什么“match”表达式没有包装在“blocking”表达式中。难道我们不希望所有的平面映射都(潜在地)花费大量的时间吗
旁注:scala.concurrent.Future类中有一个“官方”序列方法,该实现也不使用阻塞
我也会把这个发到Coursera论坛,如果我得到回复,我也会发到这里
难道我们不希望所有的平面映射都(潜在地)花费大量的时间吗
没有flatMap
只需构建一个新的Future
并立即返回。它不会阻塞
看。以下是它的简化版本:
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
时发生的情况概述:
做出承诺
添加一个回调到这个未来
还债
该方法返回一个未来
,它将完成等待所有未来的工作
我认为这种描述有点误导。您从Future.sequence
返回的Future
并不真正“起作用”。正如您在上面的代码中所看到的,您从flatMap
获得的未来
(因此,您从Future.sequence
获得的未来
)只是一个最终将由其他东西完成的承诺。唯一真正起作用的是ExecutionContext
;未来的
s只是指定要做什么
难道我们不希望所有的平面映射都(潜在地)花费大量的时间吗
没有flatMap
只需构建一个新的Future
并立即返回。它不会阻塞
看。以下是它的简化版本:
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
时发生的情况概述:
未来
,它将完成等待所有未来的工作
我认为这种描述有点误导。您从Future.sequence
返回的Future
并不真正“起作用”。正如您在上面的代码中所看到的,您从flatMap
获得的未来
(因此,您从Future.sequence
获得的未来
)只是一个最终将由其他东西完成的承诺。唯一真正起作用的是ExecutionContext
;未来的s只是指定要做什么