我想执行“流”,其中每个流并行执行。每个流本身使用期货执行操作:
def doFlow(...): Seq[Future[Something]] = {
(1 to 10) map {
Future {
Something(...)
}
}
}
val sequence: Seq[Seq[Future[Something]]] = (1 to 10) map {
iter => doFlow(...)
}
// now I want to wait for all of them to complete:
val flat: Seq[Future[Something]] = sequence.flatten
val futureSeq = Future.sequence(flat)
futureSeq.onComplete {
...
case Success(val) => {...}
}
我正在打印完成日志,我发现它们按顺序运行而不是像我想要的那样并行运行
=======================
First started at Wed Apr 18 12:02:22 IDT 2018
Last ended at Wed Apr 18 12:02:28 IDT 2018
Took 4.815 seconds
=======================
First started at Wed Apr 18 12:02:28 IDT 2018
Last ended at Wed Apr 18 12:02:35 IDT 2018
Took 4.335 seconds
=======================
First started at Wed Apr 18 12:02:35 IDT 2018
Last ended at Wed Apr 18 12:02:41 IDT 2018
Took 3.83 seconds
...
...
答案 0 :(得分:2)
在我的机器上运行:
import ExecutionContext.Implicits.global
def doFlow(chunk: Int): Seq[Future[Int]] = {
(1 to 5) map { i =>
Future {
println(s"--> chunk $chunk idx $i")
Thread.sleep(1000)
println(s"<-- chunk $chunk idx $i")
0
}
}
}
val sequence: Seq[Seq[Future[Int]]] = (1 to 5) map {
iter => doFlow(iter)
}
val flat: Seq[Future[Int]] = sequence.flatten
val futureSeq = Future.sequence(flat)
Await.ready(futureSeq, scala.concurrent.duration.Duration.Inf)
输出样本:
--> chunk 1 idx 2
--> chunk 1 idx 4
--> chunk 1 idx 1
--> chunk 1 idx 3
--> chunk 2 idx 1
--> chunk 1 idx 5
--> chunk 2 idx 3
--> chunk 2 idx 2
<-- chunk 1 idx 2
<-- chunk 2 idx 1
<-- chunk 1 idx 3
--> chunk 2 idx 5
--> chunk 3 idx 1
<-- chunk 1 idx 1
<-- chunk 1 idx 5
<-- chunk 1 idx 4
--> chunk 3 idx 3
--> chunk 2 idx 4
一次处理8个任务。
你在Something
内有任何可以引入阻塞的内部同步吗?
答案 1 :(得分:0)
Future.sequence(xs.map { x => futureY })
是要走的路。
但是,如果您的未来立即完成,或者ExecutorContext一次只处理其中一个,那么它们将是有效的顺序。
你的期货确实需要时间来执行,所以我会调查ExecutionContext。 ExecutionContext.Implicits.global
使用尽可能多的主机拥有CPU(因此,单个核心机器将具有1个线程的ExecutorService)。
为SingleThreadExecutor定义ExecutorContext也会导致顺序运行。
然后还有可能在Future中阻塞。或追查错误的事情。
要了解更多信息,我们必须查看Something(...)
的作用以及您使用的ExecutorContext是什么。