我的机器上有4个核心。
我认为for-comprehension安排在paraller中的东西(不依赖于之前的结果......相同的flatMap):
val stuffResult: Future[String] = for {
stuff1 <- service1.doServiceStuff("service 1") // worker-5 (4+1)
stuff2 <- service1.doServiceStuff("service 2")
stuff3 <- service1.doServiceStuff("service 3")
stuff4 <- service1.doServiceStuff("service 4")
} yield (stuff1 + ", " + stuff2 + ", "+ stuff3 + ", " + stuff4)
,其中
class Service {
implicit val blockingExContext = scala.concurrent.ExecutionContext.fromExecutor(null: Executor)
def doServiceStuff(name:String): Future[String] = {
Future {
blocking {
println ( s"start ${name} on " + Thread.currentThread.getName)
Thread.sleep(5000)
"stuff_done"
}
}
}
}
但我所看到的是(每一步需要约5秒):
所有在一个线程上运行,而不是使用现有的FREE线程并尽可能快地完成 - 在~5秒内。
但如果我选择:
val stuff1 = service1.doServiceStuff("service 1")
val stuff2 = service1.doServiceStuff("service 2")
val stuff3 = service1.doServiceStuff("service 3")
val stuff4 = service1.doServiceStuff("service 4")
Future.sequence(List(stuff1, stuff2, stuff3, stuff4)).map { list =>
list.foldLeft("") { (acc, x) => acc + " " + x }
}
..
所有结束都在5秒内完成。
pont for-comprehension顺序工作?是吗?
答案 0 :(得分:3)
它无法按顺序工作,它只是无法启动Future
直到它们被创建(在您的flatMap
之前的Future
中会发生这种情况,所以你如果你想并行处理它们(使用通常的隐式ExecutionContext
),需要提前创建它们。
可能this tutorial解释得更好(它使withFilter
复杂化):
购买期限仅在usdQuote和chfQuote时完成 完成 - 这取决于这两个期货的价值所以它 自己的计算不能早点开始。
上面的理解被翻译成:
val purchase = usdQuote flatMap { usd => chfQuote
.withFilter(chf => isProfitable(usd, chf))
.map(chf => connection.buy(amount, chf)) }
比理解力更难掌握,但我们更好地分析它 了解flatMap操作。 flatMap操作映射自己的 重视其他未来。一旦这个不同的未来完成, 由此产生的未来完成了它的价值。在我们的例子中, flatMap使用usdQuote future的值来映射值 chfQuote指向第三个未来发送购买某个特定的请求 瑞士法郎金额。由此产生的未来购买完成 只有从地图返回的第三个未来完成。
您真正需要的是map2
而不是flatMap
,因为您不使用上一个Future
的返回值来创建新的Future