1

正在尝试使用 Gpars 执行并发操作。

Gpars.withPool(6) {
  someList.eachParallel {
    println "${Thread.currentThread}"
  }
}

最初它似乎工作

Thread[ForkJoinPool-1-worker-1,5,main] 
Thread[ForkJoinPool-1-worker-6,5,main] 
Thread[ForkJoinPool-1-worker-2,5,main]  
Thread[ForkJoinPool-1-worker-5,5,main] 
Thread[ForkJoinPool-1-worker-3,5,main]
Thread[ForkJoinPool-1-worker-4,5,main] 
Thread[ForkJoinPool-1-worker-1,5,main]
Thread[ForkJoinPool-1-worker-6,5,main]
Thread[ForkJoinPool-1-worker-2,5,main]

但是在迭代一段时间后,一些线程停止执行。

Thread[ForkJoinPool-1-worker-2,5,main]
Thread[ForkJoinPool-1-worker-3,5,main]
Thread[ForkJoinPool-1-worker-2,5,main]
Thread[ForkJoinPool-1-worker-3,5,main] 
Thread[ForkJoinPool-1-worker-2,5,main] 
Thread[ForkJoinPool-1-worker-3,5,main]
Thread[ForkJoinPool-1-worker-2,5,main]

直到最终我们只剩下一个。

Thread[ForkJoinPool-1-worker-2,5,main]
Thread[ForkJoinPool-1-worker-2,5,main]
Thread[ForkJoinPool-1-worker-2,5,main]
Thread[ForkJoinPool-1-worker-2,5,main]
Thread[ForkJoinPool-1-worker-2,5,main]
Thread[ForkJoinPool-1-worker-2,5,main]

知道为什么会这样吗?有什么解决方案可以保持所有线程处于活动状态?

就我而言,值得一提的是,我们的迭代速度约为 50k-200k。

4

1 回答 1

0

以防万一其他人有同样的问题。他们的文件说:

因为 GParsPool 使用 Fork/Join 池(具有工作窃取),线程可能不会应用于等待处理任务,即使它们可能看起来空闲。使用工作窃取算法,无事可做的工作线程可以从仍然忙碌的其他线程中窃取任务。

如果您使用不使用 Fork/Join 的 GParsExecutorsPool ,您将获得您天真期望的线程分配行为。

基于此,我选择使用 GParsExecutorsPool 代替。如此一来,所有线程一直执行到整个 eachParallel 进程结束。

GParsExecutorsPool.withPool(6) {
  someList.eachParallel {
    println "${Thread.currentThread}"
  }
}
于 2016-10-07T14:04:40.363 回答