6. Virtual Threads
Виртуальные потоки — это легковесные потоки, которыми управляет сама JVM, а не ядро ОС. Мы можем запустить их миллионы. Код при этом остается старым добрым блочным синхронным кодом:
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
// Запускаем 10 000 одновременных запросов к БД
IntStream.range(0, 10_000).forEach(i ->
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1)); // Блочный вызов!
return fetchDataFromDb(i);
})
);
} // JVM сама запаркует поток во время sleep, не блокируя нативную память ОС
Пока один виртуальный поток ждет ответа от базы или сети, его носитель (нативная OS thread) освобождается и берет работу от другого виртуального потока. Прирост пропускной способности (*throughput*) типичного REST-сервера на сервлетах — от 2x до 10x на том же железе.
Когда НЕ стоит бежать в Virtual Threads:
* сложные математические расчеты, сжатие видео
* если весь стек зависимостей использует устаревшие библиотеки, которые хранят состояние в `ThreadLocal` в гигантских объемах (хотя большинство современных фреймворков уже адаптированы).