Gpars.withPool线程在迭代多次后最终停止执行

时间:2016-10-05 13:15:01

标签: groovy gpars

尝试使用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。

1 个答案:

答案 0 :(得分:0)

以防其他人遇到同样的问题。他们的文件说:

  

由于GParsPool使用Fork / Join池(带有工作窃取),因此线程可能不会应用于等待处理任务,即使它们可能显得空闲。使用工作窃取算法,用尽线索的工作线程可以从仍然忙碌的其他线程中窃取任务。

     

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

基于此,我选择使用GParsExecutorsPool。这样,所有线程都会一直执行,直到整个eachParallel进程结束。

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