Virtual Threads в Java (Java 21+)
Virtual Threads (Project Loom)
Виртуальные потоки (virtual threads, Project Loom) стабилизированы в Java 21 (LTS). Они позволяют запускать огромное количество задач параллельно с минимальными накладными расходами по сравнению с обычными потоками ОС.
Исторический контекст — в истории Java. Практический выбор между ExecutorService, CompletableFuture и virtual threads — в асинхронности. Краткая шпаргалка API — в справочнике.
Общая теория процессов и потоков — процессы и потоки; там же virtual threads упомянуты как лёгкие сущности над потоками ядра.
Зачем они появились
Классический java.lang.Thread — это platform thread (поток платформы): обёртка над нативным потоком ОС. На каждый такой поток уходит заметный стек (порядка мегабайта) и слот в планировщике ядра. Модель «один HTTP-запрос — один Thread» упирается в тысячи соединений, а не в миллионы.
Виртуальный поток — лёгкая задача, которую создаёт и планирует JVM, а не операционная система. Типичный сценарий — массовый блокирующий I/O (HTTP, JDBC, файлы): код остаётся синхронным (read, sleep, JDBC), а масштабирование достигается за счёт дешёвого создания потоков и умного переключения при ожидании.
| Platform thread | Virtual thread | |
|---|---|---|
| Кто создаёт | JVM → поток ОС | JVM (continuations) |
| Память на поток | ~1 МБ стека (типично) | Килобайты |
| Планировщик | ОС + JVM | JVM Scheduler поверх небольшого пула carriers |
| Лучше всего для | CPU-bound, legacy, synchronized без pinning | Много одновременных блокирующих I/O |
| С Java | 1.0 | 21+ (стабильно) |
Virtual threads не ускоряют чистые вычисления на CPU: для них по-прежнему нужен ограниченный пул platform threads или ForkJoinPool.
Три уровня — как это устроено
Виртуальные потоки создаются в прикладном коде (Thread.ofVirtual(), Executors.newVirtualThreadPerTaskExecutor()). Дальше работа идёт в три слоя:
- Virtual Thread — единица работы в коде (запрос, задача, соединение). Их может быть сотни тысяч и больше.
- Platform Thread (carrier) — «носитель»: реальный поток JVM, на котором в данный момент выполняется виртуальный поток. Пул carriers обычно сопоставим с числом ядер или чуть больше.
- OS Thread — то, что видит ядро Linux, Windows или macOS. Связь platform thread ↔ OS thread 1:1.
Связь virtual ↔ platform — M:N (много виртуальных на несколько carriers). ОС не знает о virtual threads: для планировщика ядра существуют только OS threads.
Mount и unmount при блокировке
Пока виртуальный поток выполняется на carrier, он в состоянии mounted (смонтирован).
При блокирующей операции (сокет, диск, Thread.sleep, большинство JDBC) JVM может размонтировать (unmount) virtual thread с carrier и отдать carrier другому virtual thread. Первый поток ждёт I/O «в стороне», не занимая поток ОС.
Когда I/O завершился, scheduler снова монтирует (mount) virtual thread на свободный carrier. Именно поэтому десятки тысяч «спящих» запросов не превращаются в десятки тысяч потоков ядра.
Долгий блокирующий код внутри synchronized на virtual thread может закрепить поток на carrier (pinning) и снизить выигрыш. Для нового кода предпочтительны ReentrantLock и короткие критические секции. Подробности — в JEP и release notes Java 21.
API — минимальный набор
Executor на каждую задачу (типично для сервисов):
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10_000).forEach(i ->
executor.submit(() -> handleRequest(i))
);
}
Один поток без пула:
Thread.startVirtualThread(() -> process(connection));
Явное создание:
Thread vt = Thread.ofVirtual().name("worker-", 0).start(() -> doWork());
Разбор построчно и сравнение с CompletableFuture — в асинхронности.
Когда выбирать virtual threads
| Сценарий | Рекомендация |
|---|---|
| Массовый блокирующий I/O (REST, JDBC, файлы) | virtual threads |
| CPU-bound расчёты | фиксированный пул platform threads |
| Смешанный сервис | отдельные пулы I/O и CPU + таймауты |
| End-to-end reactive стек | WebFlux / Project Reactor — Spring |
Spring Boot 3.2+ — флаг spring.threads.virtual.enabled=true на совместимом стеке (Tomcat, часть библиотек).
Эксплуатация
- Таймауты на все внешние вызовы (
orTimeout, HTTP client timeouts). - Метрики p95/p99, размер очередей, thread dump под нагрузкой — диагностика JVM.
- Graceful shutdown —
executor.close()/shutdown()при остановке контейнера. - Не смешивайте без нужды reactive и blocking-модели в одном запросе.
Сравнение с корутинами Kotlin
В Kotlin похожую модель дают корутины: лёгкие задачи и cooperative scheduling. Virtual threads ближе к привычным потокам (Thread, stack traces, отладчики) без переписывания всего API на suspend. На JVM 21+ можно комбинировать оба подхода в одном проекте, но для Java-кода virtual threads — стандартный путь масштабирования blocking I/O.
Дальше
Асинхронность · JVM и потоки · Справочник — virtual threads · История Loom · dev.java — Virtual Threads
Базовый разбор HTTP и HTTPS находится в отдельной статье — HTTP как основа веб-интеграций.
См. также
Другие статьи этого же раздела в боковом меню (как на странице "О разделе"). Основы Java - устройство JDK/JVM, модель компиляции и базовые принципы платформонезависимого выполнения. Java — объектно-ориентированный язык общего назначения с принципом «напиши один раз, запускай в любом месте». Набор советов, правил, принципов и обычаев в разработке на этом языке. История Java — от проекта Green и Oak до OpenJDK, LTS-релизов и современной платформы (модули, records, виртуальные потоки). Библиотеки, фреймворки, инструменты сборки, тестирования, развёртывания и мониторинга. Что такое пакет и пакетная структура, как собираются проекты на Java. Справочник-шпаргалка по конфигурациям в Java — типы, синтаксис, стандартная библиотека, типовые паттерны. Не заменяет пошаговое обучение. Учебный курс — раздел. Гайд по установке и настройке с написанием первой программы и её запуском. Практические примеры — консольные утилиты, композиция классов и первое Swing-приложение. Точки останова, пошаговое выполнение, панели Variables и Call Stack — практика отладки в IntelliJ IDEA. Кавычки, точки, запятые, скобки и прочие знаки препинания. Это полный справочник всех ключевых слов языка Java, включая основные, контекстные и зарезервированные слова.Основы языка Java
Что требуется знать перед началом изучения языка программирования Java
Рекомендации по разработке на Java
История языка Java
Экосистема Java-приложений
Структура и сборки Java-проектов
Справочник по конфигурациям в Java
Первая программа на Java
Простые приложения на Java
Отладка Java-кода в IDE
Синтаксис и пунктуация в Java
Ключевые слова в Java