对于我的fork-join-pool(默认全局)能够分配新线程,如果我有嵌套Futures,我是否需要用阻塞{...}包装所有单个Futures,如果它们是DB例如,电话或其他I / O /网络流程?
哪个是对的?
Future.sequence(
blocking{
val f1 = Future(...)
val f2 = Future(...)
val f3 = Future(...)
for (x <- f1; y <- f2; z <- f3) yield List(x, y, z)
}
)
或
Future.sequence(
val f1 = Future(blocking{...})
val f2 = Future(blocking{...})
...
)
编辑:
我认为这个测试(打印&#34; Futures完成&#34;然后8个睡眠线,等待5s,8个睡眠线等)表明个别阻塞调用需要使用托管阻塞包装器:
val locked =
Future.sequence {
blocking {
(0 to 100).map { i =>
Future {
val idx = i
println(s"I'm sleeping: $i")
Thread.sleep(5000)
println(s"I'm awake: $i")
}
}
}
}
println("Futures done")
答案 0 :(得分:2)
这取决于实施。
如果数据库访问或IO的实现是阻塞的,那么您应该将它们包装在blocking
。
blocking
应在每个Future
内完成。因为它们会立即开始运行。
附注:将global context
用于生产代码并不是一个好主意。
您应该定义针对您的用例优化的独立执行上下文。
您可以在此处找到详细信息:http://slick.lightbend.com/doc/3.0.0/database.html#database-thread-pool