Какие средства есть в Java для параллельной обработки данных
Что проверяют
Знаете ли вы набор инструментов от Thread до виртуальных потоков и понимаете, какой под какую нагрузку. Следом обычно спрашивают, в каком пуле работает parallelStream() и почему туда нельзя класть блокирующий ввод-вывод.
Как отвечать
ThreadиRunnable: низкий уровень, в прикладном коде напрямую почти не нужен;ExecutorService: пул потоков с очередью задач, результат черезFuture. Под капотомThreadPoolExecutorс core и max размером, очередью и политикой отказа.Executors.newFixedThreadPoolберёт неограниченную очередь, и под нагрузкой задачи копятся доOutOfMemoryError;CompletableFuture: композиция асинхронных шагов,supplyAsync,thenCombine,allOf. Без явного executor работает вForkJoinPool.commonPool();- Fork/Join:
RecursiveTaskделит задачу до порога, пул балансирует нагрузку через work stealing; - параллельные стримы:
parallelStream()делит источник черезSpliteratorи считает в общем пуле, где потоков по умолчанию на один меньше, чем ядер. Выигрыш есть на больших объёмах, на легко делимых источниках вроде массивов иArrayListи без общего состояния; - виртуальные потоки: с Java 21,
Executors.newVirtualThreadPerTaskExecutor(). Для тысяч задач, которые ждут сеть или базу, а не считают. С Java 24synchronizedбольше не закрепляет виртуальный поток за несущим; - structured concurrency:
StructuredTaskScopeдля группы связанных подзадач, пока в статусе preview.
Для общих данных ConcurrentHashMap, AtomicLong, LongAdder, для координации CountDownLatch и Phaser. Данные больше одной машины это уже Spark или Flink.
Где спотыкаются
Кладут HTTP-запросы или JDBC в parallelStream(). Общий пул маленький, блокировки занимают его целиком, и встают все параллельные стримы и CompletableFuture приложения.
Меняют общую коллекцию из лямбды: parallelStream().forEach(list::add) в обычный ArrayList теряет элементы или падает. Собирать нужно через collect или toList().
Считают, что чем больше потоков, тем быстрее. Для вычислений потолок это число ядер, дальше растут переключения контекста, а виртуальные потоки CPU-bound задачу не ускорят.