В каких случаях parallel stream, скорее всего, не даст выигрыша или окажется медленнее последовательного?
Выигрыша нет, когда мало данных или дешёвая операция (N × Q мало), источник плохо делится (LinkedList, Stream.iterate, итератор), есть сохранение порядка (forEachOrdered, limit, findFirst) или дорогое слияние (collect в коллекции).
- Хорошо делятся массивы, ArrayList, IntStream.range
- Упаковка Integer съедает выигрыш — примитивные стримы
- Общий пул делят с другими задачами
А ещё Решают только измерения (JMH)
Подробно
Практическое правило звучит как произведение числа элементов на стоимость обработки одного: пока оно мало, параллелизм только добавляет расходов на разбиение, передачу задач и слияние результатов. Хорошо делятся источники с произвольным доступом и известным размером — массивы, ArrayList, IntStream.range; плохо — связные списки и потоки, размер которых заранее неизвестен. Дорогое слияние тоже способно съесть выигрыш: например, сборка в неупорядоченный набор дешевле, чем в упорядоченный список. Отдельно стоит помнить про ловушки корректности: forEach в параллельном стриме не гарантирует порядок (для порядка есть forEachOrdered), а любые побочные эффекты на общем изменяемом состоянии дают гонки. Неизменяемость элементов, напротив, параллелизму только помогает.
Что хотят услышать
- Условия, при которых параллелизм вредит.
- Хорошие и плохие источники.
Частые ошибки
- Ставить .parallel() без замера и без учёта размера данных.
- Изменять общее состояние из параллельного стрима.
Проверьте себя
Несколько верных вариантов. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Элементы коллекции неизменяемы, поэтому потокам приходится копировать их перед обработкой
- ✓Коллекция мала, а операция дешёвая — разбиение и слияние дороже
- ✓Источник плохо делится: LinkedList или поток из итератора
- ✓Нужно сохранять порядок, или слияние результатов само дорого
Что спросят дальше
- Почему ArrayList делится лучше, чем LinkedList?
- Чем forEach отличается от forEachOrdered?
Разбор темы
- ThreadLocal и Fork/Join
Состояние на поток и утечки в пулах, InheritableThreadLocal, work-stealing в ForkJoinPool и общий пул parallel streams.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.