[英]Why is Scala Future running sequentially when mapped over an Iterator
所以我很困惑为什么用 Futures 映射一个迭代器会使它按顺序运行。 考虑以下代码 -
import org.scalameter._
object IteratorVsListInFutures extends App {
def slowFunction = Thread.sleep(1000)
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import duration._
println("Should take approximately 4000 ms or 4 sec")
println{
withWarmer(new Warmer.Default) measure {
List(1,2,3,4).foreach(_ => slowFunction)
}
}
println("Should take approximately 1 second")
println {
withWarmer(new Warmer.Default) measure {
val futures: Seq[Future[Unit]] = List(1,2,3,4).map(_ => Future { slowFunction})
futures.foreach(x => Await.result(x, 10.seconds))
}
}
println("And how long does this take")
println {
withWarmer(new Warmer.Default) measure {
val futures = List(1,2,3,4).iterator.map(_ => Future { slowFunction})
futures.foreach(x => Await.result(x, 10.seconds))
}
}
}
我得到以下结果 -
Should take approximately 4000 ms or 4 sec
4012.132085 ms
Should take approximately 1 second
1004.997573 ms
And how long does this take
4016.533206 ms
Process finished with exit code 0
第一个基准与预测约 4 秒,第二个基准也与预测约 1 秒(因为期货是并行执行的)让我困惑的是为什么第三个基准也是约 4 秒?
由于迭代器的非严格性质,以下
List(1,2,3,4).iterator.map(_ => Future { slowFunction })
计算为Iterator[Future[Unit]]
,这只是对要发生的转换的描述,但尚未发生。 关键是要明白
惰性集合对于描述连续的转换操作而不评估中间转换特别有用
让我们稍微重写您的示例以强调中间转换
List(1,2,3,4)
.iterator
.map(_ => Future { slowFunction }) // <-- intermediate transformation
.foreach(x => Await.result(x, 10.seconds))
因此map(_ => Future { slowFunction })
是没有被评估的中间转换,但这是应该启动期货的转换。 相反, map
转换与foreach
转换相结合,作为一个单一的转换来执行,像这样
List(1,2,3,4)
.foreach(_ => Await.result(Future { slowFunction }, 10.seconds) )
现在可以明确的是,我们正在等待完成Future
我们移动到下一个元素,因此之前Future
氏完全连续。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.