为了让我的 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{...})
...
)
编辑:
我认为这个测试(打印“Futures done”,然后 8 个 hibernate 行,等待 5 秒,8 个 hibernate 行等)表明各个阻塞调用需要使用托管阻塞包装器:
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")
最佳答案
这取决于实现。
如果数据库访问或 IO 的实现是阻塞的,那么您应该将它们包装在阻塞
中。
阻塞
应该在每个Future
内完成。因为它们会立即开始运行。
旁注:对生产代码使用全局上下文
并不是一个好主意。
您应该定义针对您的用例进行优化的单独执行上下文。
对于您巧妙的用例,您可以在此处找到详细信息:http://slick.lightbend.com/doc/3.0.0/database.html#database-thread-pool
关于java - 嵌套 Scala Future 是否需要托管阻塞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37554416/