В чем разница между ForkJoinPool.commonPool () и новым ForkJoinPool (доступно для ЦПУ - 1)? - PullRequest
0 голосов
/ 05 февраля 2019

В моем коде у меня есть класс, содержащий статическую конечную переменную

private static final ForkJoinPool pool = new ForkJoinPool(availableCPUs - 1);

У меня есть долгосрочное задание, отправленное в пул, который потребляет все ресурсы процессора.Любые другие представленные задания будут зависать.Однако, когда я переключился на создание общего пула

private static final ForkJoinPool pool = ForkJoinPool.commonPool();

Все задачи могут быть отправлены и выполнены.

Мне было просто интересно, в чем различия между этими двумя частями кода.commonPool() все еще вызывает new ForkJoinPool() и передает availableCPUs - 1

Также я заметил, что commonPool() использует фабрику типа SafeForkJoinWorkerThreadFactory, в то время как new ForkJoinPool() использует ForkJoinPool$DefaultForkJoinWorkerThreadFactory.Имеет ли это значение?

Большое спасибо!

Ответы [ 2 ]

0 голосов
/ 06 февраля 2019

Думаю, я понял это.

ForkJoin поддерживает два типа очередей: одну общую очередь входящих и очереди рабочих потоков для каждого рабочего потока.Все рабочие потоки сначала будут извлекаться из общей входящей очереди и заполнять свои рабочие потоки.После того, как один рабочий поток завершит все задачи в своей рабочей очереди, он попытается украсть из других рабочих потоков.Если нет другой задачи для кражи из других рабочих потоков, рабочий поток снова будет извлекать данные из общей входящей очереди.

Однако при использовании общего пула основной поток также помогает обрабатывать задачи.Основной поток не имеет рабочей очереди, хотя.Следовательно, после завершения одной задачи основной поток сможет извлечь из общей входящей очереди.

Поскольку по умолчанию очереди ForkJoin имеют тип LIFO, основной поток сможет получать последние отправленные задачи.

0 голосов
/ 05 февраля 2019

Документация говорит:

Общий пул по умолчанию создается с параметрами по умолчанию.

ForkJoinPool()

Создает ForkJoinPool с параллелизмом, равным Runtime.availableProcessors(), используя фабрику потоков по умолчанию , без UncaughtExceptionHandler, ине асинхронный режим обработки LIFO.

Так с чего вы взяли, что new ForkJoinPool(availableCPUs - 1) и ForkJoinPool.commonPool() будут пулами одинакового размера?

Если у вас только 2 процессора,тогда availableCPUs - 1 означает, что вы создаете пул из 1 потока, то есть он может обрабатывать только одну задачу за раз, поэтому долго выполняющаяся задача блокирует все другие задачи.

Но с двумя ЦП availableProcessors() означает, что вы получаете общий пул с 2 потоками, то есть он может обрабатывать другие задачи во время обработки одной длительной задачи.

...