Ответ
Параллельный стрим — это стрим API, который выполняет операции, используя несколько потоков из общего ForkJoinPool, для потенциального ускорения обработки больших объемов данных.
Создание:
List<String> list = Arrays.asList("a", "b", "c");
// Способ 1:
Stream<String> parStream1 = list.parallelStream();
// Способ 2:
Stream<String> parStream2 = list.stream().parallel();
Когда использовать:
- Обработка больших коллекций.
- CPU-интенсивные операции над элементами (например, сложные вычисления).
- Порядок обработки не важен, либо используется
forEachOrdered().
Пример вычисления суммы:
long sum = LongStream.rangeClosed(1, 10_000_000)
.parallel() // Включаем параллельную обработку
.sum();
Важные предостережения:
- Избегайте изменяемого состояния: Операции (лямбды) должны быть stateless и не модифицировать общие данные, чтобы не возникало состояний гонки.
- Накладные расходы: Для маленьких коллекций или простых операций (
println) накладные расходы на управление потоками могут сделать параллельный стрим медленнее последовательного. - Порядок выполнения:
forEach,findAnyне гарантируют порядок. ИспользуйтеforEachOrderedдля сохранения порядка. - Общий пул: По умолчанию используется общий
ForkJoinPool.commonPool(). Длительные блокирующие операции (I/O) в параллельных стримах могут истощить его, негативно влияя на другие части приложения.
Ответ 18+ 🔞
Да ты посмотри, что выдумали, блядь! Параллельный стрим, ёпта! Это когда твоя коллекция такая здоровая, что один поток с ней ебётся до второго пришествия, а тут — хуяк! — и несколько потоков из общего ForkJoinPool на неё набрасываются. В теории, чтобы всё быстрее сожрать, конечно.
Как эту хуйню создать, спрашиваешь?
List<String> list = Arrays.asList("a", "b", "c");
// Способ первый, классический:
Stream<String> parStream1 = list.parallelStream();
// Способ второй, для тех, кто любит поизвращаться:
Stream<String> parStream2 = list.stream().parallel();
А когда это вот вообще применять-то, блядь?
- Когда у тебя коллекция огромная, просто овердохуища элементов.
- Когда над каждым элементом нужно мозги ебать — сложные вычисления, CPU грузить.
- Когда порядок, в каком они там пережёвываются, тебе похуй. Или если не похуй, то используешь
forEachOrdered(), чтоб не пиздец.
Вот, смотри, как сумму для вида посчитать:
long sum = LongStream.rangeClosed(1, 10_000_000)
.parallel() // Включаем режим "ебём всем скопом"
.sum();
А теперь слушай сюда, самое важное, чтоб не обосраться:
- Не лезь в общее говно! Все твои операции (эти лямбды) должны быть святыми — stateless. Никакого изменения общих переменных извне, а то получишь состояние гонки, и будет тебе пиздец, а не ускорение.
- Не для всего это волшебство. Если коллекция маленькая или операция простая (типа
println), то накладные расходы на управление потоками сделают параллельный стрим медленнее, чем если бы один поток всё сделал. Получишь хуй в пальто, а не результат. - Порядок — не гарант. Методы вроде
forEachилиfindAnyмогут выдать результат в каком попало порядке. Хочешь по порядку —forEachOrderedтебе в помощь, мартышлюшка. - Общий пул — он общий, блядь. Все по умолчанию лезут в один
ForkJoinPool.commonPool(). Если сунешь туда долгие блокирующие операции (типа I/O), то можешь этот пул так выебать, что и остальное приложение встанет колом. Подозрение ебать чувствую, что так и сделаешь.