Stream API и параллельные потоки в Java (4/10)
⚠️ В этом посте я не учу Stream API — я показываю, как Java может обрабатывать большие наборы данных параллельно и просто. Для запуска используйте JDK 17+ и любую IDE.
Мы уже научились запускать потоки, синхронизировать их и писать асинхронный код. Теперь давай посмотрим, как Java умеет ускорять обработку данных буквально одной строкой — без ручного управления потоками.
Иногда не нужно создавать Thread — просто добавь .parallel()
☕ Пример: считаем кофе по регионам
Допустим, у нас есть список заказов из разных регионов. Мы хотим посчитать, сколько кофе сварили в каждом регионе.
import java.util.; import java.util.stream.;
public class CoffeeStats { public static void main(String[] args) { List orders = Arrays.asList( "Asia", "Europe", "Europe", "Asia", "America", "Asia", "Europe", "America", "Europe", "Asia" );
Map stats = orders .parallelStream() // магия начинается здесь .collect(Collectors.groupingBy(region -> region, Collectors.counting()));
stats.forEach((region, count) -> System.out.println("🌍 " + region + ": " + count + " чашек кофе")); } }
⚡ Что делает .parallelStream()?
- Делит список на подзадачи. 2( Обрабатывает их в нескольких потоках.
- Собирает результат автоматически.
То есть Java сама решает, как распределить нагрузку по ядрам процессора. Ты просто пишешь декларативно - “что” нужно сделать, а не “как”.
Сравнение: stream vs parallelStream
orders.stream().forEach(System.out::println); // последовательно orders.parallelStream().forEach(System.out::println); // параллельно
Второй вариант выведет строки в разном порядке — потому что потоки работают независимо. Если порядок важен — используй .forEachOrdered().
🧩 Когда параллельные потоки — благо, а когда нет
✅ Отлично подходят, если:
- Много независимых элементов для обработки.
- CPU имеет несколько ядер.
- Задачи CPU-bound (тяжёлые вычисления).
❌ Лучше не использовать, если: 4) Мало данных (накладные расходы будут больше). 5) Есть взаимодействие с внешними ресурсами (файлы, БД, сеть). 6) Порядок важен и нельзя его нарушать.
🔍 Продвинутый пример. Можно комбинировать фильтрацию, маппинг и группировку — всё параллельно:
Map hotRegions = orders .parallelStream() .filter(region -> !region.equals("America")) .collect(Collectors.groupingBy(r -> r, Collectors.counting()));
System.out.println("🔥 Активные регионы: " + hotRegions);
🧭 Итоги
- .parallelStream() — быстрый способ параллелить задачи без лишнего кода.
- Работает “из коробки” - Java сама решает, сколько потоков нужно.
- Помогает эффективно использовать многоядерные процессоры.
- Параллельность - не всегда панацея, думай о балансе.
Как и в жизни: иногда стоит делать всё сразу, а иногда - просто по порядку и с умом. Главное - знать, когда включать наш так называемый “параллельный режим”.