У меня есть массив некоторых объектов с методом process (), который я хочу запустить распараллеливанием. И я хотел попробовать лямбды, чтобы добиться распараллеливания. Итак, я попробовал это:
Arrays.asList(myArrayOfItems).forEach(item->{
System.out.println("processing " + item.getId());
item.process();
});
Каждый вызов process () занимает около 2 секунд. И я заметил, что при «распараллеливании» все еще нет ускорения. Кажется, что все еще сериализовано. Идентификаторы печатаются последовательно (по порядку), и между каждым отпечатком делается пауза в 2 секунды.
Наверное, я что-то неправильно понял. Что необходимо, чтобы выполнить это параллельно с использованием лямбда-выражений (надеюсь, в очень сжатой форме)?
Спасибо, parallelStream () решил мою проблему




Метод Collection.forEach () - это просто итерация по всем элементам. Он называется внутренняя итерация, поскольку он оставляет до коллекции как, которую он будет повторять, но это все еще итерация для всех элементов.
Если вам нужна параллельная обработка, вам необходимо:
Вы можете прочитать первую часть моего объяснения здесь: https://stackoverflow.com/a/22942829/2886891
Чтобы создать параллельный поток, вызовите операцию .parallelStream в Коллекции.
См. https://docs.oracle.com/javase/tutorial/collections/streams/parallelism.html
Arrays.asList(myArrayOfItems).parallelStream().forEach(item->{
System.out.println("processing " + item.getId());
item.process();
});
Сами лямбды ничего не выполняют параллельно. Однако Stream способны на это.
Взгляните на метод Collection#parallelStream (документация):
Arrays.asList(myArrayOfItems).parallelStream().forEach(...);
Однако обратите внимание, что нет никакой гарантии или контроля, когда он действительно будет идти параллельно. Из его документации:
Returns a possibly parallel Stream with this collection as its source. It is allowable for this method to return a sequential stream.
Причина проста. Вам действительно нужно много элементов в вашей коллекции (например, миллионы) для того, чтобы распараллеливание действительно окупилось (или для выполнения других тяжелых вещей). Накладные расходы, связанные с распараллеливанием, составляют огромный. Из-за этого метод может вместо этого использовать последовательный поток, если считает, что он будет быстрее.
Прежде чем вы подумаете об использовании параллелизма, вам следует установить несколько тестов, чтобы проверить, улучшает ли он что-либо. Есть много примеров, когда люди просто слепо использовали его, не замечая, что они на самом деле снизили производительность. Также см. Должен ли я всегда использовать параллельный поток, когда это возможно?.
Вы можете проверить, параллелен ли Stream, используя Stream#isParallel (документация).
Если вы используете Stream#parallel (документация) непосредственно в потоке, вы получаете параллельную версию.
Я думаю, что это был бы лучший ответ, хотя у него есть один недостаток: когда каждая операция занимает 2 секунды, она действительно окупается за гораздо меньшее количество операций, чем миллионы, когда пользователь ищет плавный опыт.
Это верно. Просто обратите внимание, что параллелизм приводит к огромным накладным расходам, и вы не должны слепо использовать его везде, не задумываясь об этом или фактически измеряя время.
заказное исполнение в моем случае не требуется
Вы имели в виду
.parallelStream().forEach(item -> {..