Подтвердить что ты не робот

Сколько потоков генерируется в parallelStream в Java 8?

В JDK8 сколько потоков возникает, когда я использую parallelStream? Например, в коде:

list.parallelStream().forEach(/** Do Something */);

Если этот список содержит 100000 элементов, сколько потоков будет создано?

Кроме того, чтобы каждый из потоков получал одинаковое количество элементов для работы или был ли он случайным образом распределен?

4b9b3361

Ответ 1

Реализация Oracle [1] параллельного потока использует текущий поток и в дополнение к этому, если необходимо, также потоки, которые составляют пул соединений fork по умолчанию ForkJoinPool.common(), который имеет размер по умолчанию, равный единице меньше, чем количество ядер вашего процессора.

Этот размер по умолчанию для общего пула может быть изменен с помощью этого свойства:

-Djava.util.concurrent.ForkJoinPool.common.parallelism=8

В качестве альтернативы вы можете использовать свой собственный пул:

ForkJoinPool myPool = new ForkJoinPool(8);
myPool.submit(() ->
    list.parallelStream().forEach(/* Do Something */);
).get();

Что касается заказа, задания будут выполняться, как только поток будет доступен, в определенном порядке.

[1] Как правильно указано @Holger, это конкретная деталь реализации (с помощью одна неопределенная ссылка в нижней части документа), оба подхода будут работать над Oracle JVM, но определенно не гарантируют работу с JVM от других поставщиков, свойство не может существовать в реализации, отличной от Oracle, и Streams не может даже использовать ForkJoinPool, предоставляя альтернативу, основанную на поведение ForkJoinTask.fork полностью бесполезно (см. здесь для получения подробной информации об этом).

Ответ 2

В то время как @uraimo верен, ответ зависит от того, что именно делает "Do Something". API parallel.stream использует класс CountedCompleter, который имеет некоторые интересные проблемы. Поскольку структура F/J не использует отдельный объект для хранения результатов, длинные цепочки могут приводить к OOME. Также эти длинные цепи могут иногда вызывать переполнение стека. Ответ на эти проблемы - использование метода Paraquential, как я указал в этой статье.

Другой проблемой является чрезмерное создание потоков при использовании вложенных параллельных forEach.