В parallel stream выполняется обращение к внешнему HTTP-сервису. Почему это опасно для всего приложения?
Parallel stream выполняется в общем ForkJoinPool.commonPool — одном на JVM, размером «ядра − 1». Блокирующий HTTP-вызов занимает его потоки, и встают все parallel stream и async-стадии приложения, включая чужие библиотеки.
- Сетевые вызовы — свой executor и CompletableFuture или виртуальные потоки
- Отладить трудно: тормозит код, который не менялся
- Запуск внутри своего ForkJoinPool — недокументированный трюк
А ещё Parallel stream — только для CPU-bound и больших объёмов
Подробно
Общий ForkJoinPool задумывался под короткие вычислительные задачи, которые никогда не блокируются. Стоит поместить туда сетевой вызов на секунду — и все остальные параллельные стримы приложения, включая чужие библиотеки, встают в очередь. Отладить это тяжело: тормозит код, который вы не меняли. Варианты решения: не использовать parallel stream для блокирующих операций вовсе; выполнить стрим внутри задачи, отправленной в собственный ForkJoinPool (известный обходной приём); либо взять ExecutorService или виртуальные потоки, которые для такой нагрузки подходят гораздо лучше. Общее правило: parallel stream — инструмент для CPU-bound обработки больших объёмов данных в памяти, и никак не для ввода-вывода.
Что хотят услышать
- Общий пул и его размер.
- Последствия блокировки.
- Правильная альтернатива.
Частые ошибки
- Добавлять .parallel() ради ускорения операций ввода-вывода.
- Не учитывать, что общий пул разделяется со всем приложением.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Parallel stream создаёт новый поток на каждый элемент
- ✗Ничего страшного: общий пул автоматически расширится под блокирующую нагрузку
- ✓Он занимает общий commonPool, и тормозят все parallel stream
- ✗HTTP-клиенты нельзя вызывать из нескольких потоков
Что спросят дальше
- Как задать собственный пул для parallel stream?
- Чему равен параллелизм общего пула по умолчанию?
Разбор темы
- ThreadLocal и Fork/Join
Состояние на поток и утечки в пулах, InheritableThreadLocal, work-stealing в ForkJoinPool и общий пул parallel streams.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.