middle
Расскажите о параллельной обработке в Java 8
Параллельные стримы позволяют автоматически распределить обработку данных по нескольким ядрам процессора. Данные разбиваются на части, каждая часть обрабатывается в отдельном потоке, а затем результаты объединяются. Под капотом используется общий ForkJoinPool (доступен через ForkJoinPool.commonPool()).
Создание параллельного стрима
Пример
// Из коллекции
collection.parallelStream();
// Из существующего стрима
stream.parallel();
// Проверка
stream.isParallel(); // true/false
Переключение между режимами
Пример
collection.stream()
.peek(...) // последовательно
.parallel()
.map(...) // параллельно
.sequential()
.reduce(...); // последовательно
Когда параллельные стримы эффективны
| Фактор | Хорошо | Плохо |
|---|---|---|
| Размер данных | Большие объёмы (>10K элементов) | Малые объёмы |
| Структура данных | ArrayList, массивы (легко разбить) |
LinkedList (трудно разбить) |
| Тип данных | Примитивы | Объекты с тяжёлым autoboxing |
| Тип операций | Короткие CPU-bound операции | Долгие I/O операции, блокировки |
| Порядок | Не важен | Важен (forEachOrdered добавляет overhead) |
Важные ограничения
- Все параллельные стримы в JVM делят один
ForkJoinPool— долгая операция в одном стриме может заблокировать другие - Для сохранения порядка используйте
forEachOrdered()вместоforEach() unordered()может повысить производительность, если порядок не важен- На одноядерной машине параллельный стрим выполняется последовательно
Пример с unordered
collection.parallelStream()
.sorted()
.unordered()
.collect(Collectors.toList());
На собеседовании: не говорите, что параллельные стримы «всегда быстрее». Интервьюер ожидает понимания компромиссов: overhead на разбиение и объединение данных, общий
ForkJoinPool, проблемы сLinkedList. Золотое правило — измерять (benchmark), а не угадывать.