CompletableFuture
Тема дорожной карты · Java
CompletableFuture — основной строительный блок для неблокирующего асинхронного программирования в Java, введённый в Java 8 как реализация Future<T> и CompletionStage<T>, поддерживающая ручное завершение, обработку исключений и создание цепочек зависимых действий. В отличие от старого интерфейса Future, CompletableFuture позволяет компоновать асинхронные конвейеры с методами thenApply() (преобразование результата), thenAccept() (потребление без возврата), thenCompose() (flatMap в другой CompletableFuture) и thenCombine() (слияние двух независимых futures) — всё это без блокировки вызывающего потока. CompletableFuture.supplyAsync(supplier, executor) выполняет вычисление в предоставленном пуле потоков из Java Executor Framework — по умолчанию ForkJoinPool.commonPool() при отсутствии executor, — тогда как exceptionally() и handle() позволяют восстанавливаться после сбоев прямо в цепочке без оборачивания всей цепочки в try-catch. CompletableFuture лежит в основе реактивно-подобных паттернов в адаптерах Spring WebFlux и широко используется вместе с ExecutorService и утилитами Java Concurrency для оркестрации параллельных вызовов к источникам данных JDBC, REST-эндпоинтам или кешам. Понимание CompletableFuture обязательно для написания производительных микросервисов на Java, которым необходимо распараллеливать несколько независимых I/O-вызовов и агрегировать их результаты без блокировки ценных серверных потоков.
Как это работает
CompletableFuture имеет много инструментов: Thread (низкоуровневый), Executor / ExecutorService (пулы потоков), CompletableFuture (async-композиция), Future, java.util.concurrent коллекции (ConcurrentHashMap, BlockingQueue, CopyOnWriteArrayList), атомарные примитивы (AtomicInteger, AtomicReference). Java 21 даёт virtual threads (Project Loom — миллионы лёгких потоков, идеально для I/O-bound). Синхронизация: synchronized, ReentrantLock, ReadWriteLock, StampedLock. Memory model (JMM) управляет видимостью.
Когда применять
ExecutorService вместо сырых Thread — пулы управляют жизненным циклом. CompletableFuture — для async-композиции (thenApply, thenCompose, allOf). На Java 21+ virtual threads делают блокирующий I/O практичным на высокой конкурентности (Executors.newVirtualThreadPerTaskExecutor()). ConcurrentHashMap — для shared-state. Прочтите "Java Concurrency in Practice" до серьёзного concurrent-кода.
Типичные ошибки
Ловушки CompletableFuture: shared mutable state без синхронизации (visibility-баги); volatile-"фикс" для race, требующих атомарности (volatile только видимость, не атомарный RMW); deadlock из-за двух локов в разном порядке; не daemon-threads когда нужно (JVM висит при shutdown); слишком много потоков для I/O-bound до Loom (новый ответ — virtual threads).