Потоки Gpars.withPool в конечном итоге перестают выполняться после многократного повторения
Пытался выполнить параллельные операции с 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]
Есть идеи, почему это происходит? Любое решение, чтобы сохранить все потоки активными?
В моем случае, возможно, стоит упомянуть, что мы выполняем итерацию в диапазоне 50–200 тыс.
1 ответ
На всякий случай у других людей такая же проблема. Их документация гласит:
Поскольку GParsPool использует пул Fork/Join (с перехватом работы), потоки не могут быть применены к задаче ожидающей обработки, даже если они могут показаться неактивными. С помощью алгоритма кражи рабочих потоков рабочие потоки, у которых заканчивается работа, могут красть задачи из других потоков, которые все еще заняты.
если вы используете GParsExecutorsPool, который не использует Fork/Join, вы получите поведение распределения потоков, которое вы наивно ожидаете.
Исходя из этого, я предпочитаю использовать GParsExecutorsPool вместо этого. При этом все потоки выполняются последовательно до конца всего процесса каждого параллельного процесса.
GParsExecutorsPool.withPool(6) {
someList.eachParallel {
println "${Thread.currentThread}"
}
}