Virtual threads (Java 21)
Тема дорожной карты · Java
Virtual Threads в Java — это лёгкие, управляемые JVM потоки, введённые как стабильная функция в Java 21 (JEP 444) через Project Loom, предназначенные для того, чтобы высококонкурентное I/O-ёмкое программирование стало столь же простым, как написание последовательного блокирующего кода без потери масштабируемости. В отличие от платформенных потоков — обёрток 1:1 вокруг дорогостоящих потоков ОС, ограниченных десятками тысяч на JVM-процесс, — Virtual Threads в Java являются объектами, выделяемыми в куче, планируемыми JVM на небольшой пул потоков-носителей платформы через ForkJoinPool, что позволяет создавать миллионы Virtual Threads с минимальными накладными расходами. Virtual Threads в Java создаются через Thread.ofVirtual().start(task), Thread.startVirtualThread(runnable) или Executors.newVirtualThreadPerTaskExecutor(), и прозрачно интегрируются с synchronized, ReentrantLock, JDBC, блокирующими операциями NIO и ThreadLocal. Начиная с JDK 24 (JEP 491) блокировка внутри synchronized и вызов Object.wait() больше не закрепляют («пиннят») поток-носитель — виртуальный поток корректно отмонтируется; закрепление остаётся только при блокировке в нативных фреймах (JNI). Старый совет «предпочитайте ReentrantLock вместо synchronized» актуален лишь для Java 21–23. Spring Boot 3.2+ включает Virtual Threads для Tomcat, Jetty и выполнения @Async через единственное свойство (spring.threads.virtual.enabled=true), позволяя существующему блокирующему коду Spring MVC, Spring Data JPA и JDBC обслуживать высокую конкурентность запросов без переписывания в реактивном стиле. Virtual Threads в Java выполняют обещание Project Loom: структурированная конкурентность через StructuredTaskScope (по-прежнему preview-API — JEP 505 в JDK 25) дополнительно упрощает паттерны ветвления, отмену и распространение ошибок, которые раньше требовали сложных цепочек CompletableFuture или реактивных операторов.
Как это работает
Virtual threads (Java 21) имеет много инструментов: 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-кода.
Типичные ошибки
Ловушки Virtual threads (Java 21): shared mutable state без синхронизации (visibility-баги); volatile-"фикс" для race, требующих атомарности (volatile только видимость, не атомарный RMW); deadlock из-за двух локов в разном порядке; не daemon-threads когда нужно (JVM висит при shutdown); слишком много потоков для I/O-bound до Loom (новый ответ — virtual threads).
Связанные понятия
Полезные ресурсы
Проверить знания (2)
Загрузка вопросов…