Чем отличаются корутины, Virtual Threads и Platform Threads?
Все три механизма предназначены для организации параллельного и конкурентного выполнения, но отличаются уровнем абстракции, управлением и применимостью.
Platform Threads (потоки платформы)
Обёртка над потоками ОС (kernel threads). Каждый Platform Thread = один поток ОС.
Пример
Thread thread = new Thread(() -> System.out.println("Platform Thread"));
thread.start();
- Управляются планировщиком ОС (вытесняющее планирование)
- Стек ~1 МБ (фиксированный)
- Создание и переключение контекста дорогие
- Лимит — тысячи потоков на JVM
- Подходят для CPU-bound задач
Virtual Threads (Java 21)
Легковесные потоки, управляемые JVM. Модель M:N — множество виртуальных потоков на нескольких carrier threads.
Пример
Thread vThread = Thread.ofVirtual().start(() -> System.out.println("Virtual Thread"));
- Управляются JVM (continuation-based)
- Стек — несколько КБ, динамический рост (heap)
- Создание и переключение — крайне дешёвые
- Можно создать миллионы
- При блокировке JVM «отсоединяет» от носителя
- Полная совместимость с существующим API
Thread - Подходят для IO-bound задач
Корутины (Kotlin Coroutines)
Конструкция уровня языка Kotlin (не JVM). Кооперативная многозадачность — приостановка в явных точках suspend.
Пример
suspend fun fetchData(): String {
delay(1000) // Suspend point — НЕ блокирует поток
return "данные"
}
fun main() = runBlocking {
launch { println(fetchData()) }
}
- Кооперативное планирование (приостановка только в
suspend-функциях) - Structured Concurrency встроена с самого начала
- Не являются потоками — это приостанавливаемые вычисления
- Потребление — несколько сотен байт
Сравнительная таблица:
| Характеристика | Platform Thread | Virtual Thread | Корутина (Kotlin) |
|---|---|---|---|
| Уровень | ОС | JVM | Язык (Kotlin) |
| Планирование | Вытесняющее (ОС) | Вытесняющее (JVM) | Кооперативное |
| Стоимость создания | ~1 мс | ~1 мкс | Очень низкая |
| Потребление памяти | ~1 МБ | ~несколько КБ | ~сотни байт |
| Макс. количество | Тысячи | Миллионы | Миллионы |
| Точки переключения | Любое место | Блокирующие операции | Только suspend |
| Structured Concurrency | Нет | StructuredTaskScope (preview) |
Встроена |
| Совместимость с Java API | Полная | Полная | Через адаптеры |
| CPU-bound | Подходит | Не лучше Platform | Dispatchers.Default |
| IO-bound | Не масштабируется | Отлично | Отлично |
Когда что использовать:
Пример
// 1. CPU-bound → Platform Threads (ForkJoinPool)
ForkJoinPool pool = new ForkJoinPool(Runtime.getRuntime().availableProcessors());
pool.submit(() -> heavyComputation());
// 2. IO-bound (Java) → Virtual Threads
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> callExternalApi());
executor.submit(() -> queryDatabase());
}
Пример
// 3. IO-bound (Kotlin) → Корутины
coroutineScope {
async(Dispatchers.IO) { callExternalApi() }
async(Dispatchers.IO) { queryDatabase() }
}
Как обрабатывается блокировка:
- Virtual Thread: JVM автоматически unmount при блокирующем вызове, прозрачно для кода.
- Корутина: блокировка только в
suspend-точках; обычный блокирующий вызов заблокирует поток диспетчера.
Ключевые различия в философии:
- Virtual Threads — используют существующий блокирующий API, JVM делает его неблокирующим «под капотом».
- Корутины — новый синтаксис (
suspend), больше контроля (диспетчеры, каналы), явные точки приостановки. - Kotlin-корутины могут работать поверх Virtual Threads, объединяя преимущества обоих.
Частые ошибки:
- Virtual Threads для CPU-bound — не даёт преимущества.
- Блокировка в корутинах вне
Dispatchers.IO— голодание общего пула. - Замена всех Platform Threads на Virtual без анализа — pinning в
synchronized.
Тренд 2024-2026: отказ от реактивных фреймворков (WebFlux, RxJava) в пользу Virtual Threads для новых проектов, где реактивность использовалась только ради масштабируемости IO.
Аналогия: Platform Thread — это курьер на автомобиле: дорогой, но выполняет любую работу. Virtual Thread — курьер на велосипеде: дешёвый, по городу (IO) быстрее, но тяжёлый груз (CPU) не потянет. Корутина — дрон: ещё легче, летает быстро, но требует специальную инфраструктуру (Kotlin runtime) и умеет приземляться только в отмеченных точках (suspend).
На собеседовании важно показать, что вы понимаете: это не конкурирующие, а взаимодополняющие технологии. Platform Threads — фундамент, Virtual Threads — масштабируемость IO в Java, корутины — экосистема Kotlin. Прямое сравнение производительности некорректно, так как они работают на разных уровнях.