[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-mnogopotochnost-chto-takoe-virtual-threads-project-loom-i-chem-oni-otlichayutsya-ot-platform-threads":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":21,"progress":22,"seo":23},296,"chto-takoe-virtual-threads-project-loom-i-chem-oni-otlichayutsya-ot-platform-threads",8,"mnogopotochnost","Многопоточность","🔀","Что такое Virtual Threads (Project Loom) и чем они отличаются от Platform Threads?","\u003C!-- grade: 5\u002F5 — подробный, актуальный ответ с примерами и практическими рекомендациями -->\n\n**Virtual Threads** (виртуальные потоки) — это легковесные потоки, появившиеся в Java 21 (JEP 444) как стабильная функциональность. Они управляются JVM, а не операционной системой, и позволяют создавать **миллионы потоков** одновременно с минимальными затратами.\n\n**Platform Threads** — это традиционные потоки Java, являющиеся тонкой обёрткой над потоками ОС. Каждый занимает ~1 МБ стека и требует системных ресурсов для создания и переключения контекста.\n\n**Сравнительная таблица:**\n\n| Характеристика | Platform Thread | Virtual Thread |\n|---|---|---|\n| Управление | ОС | JVM |\n| Потребление памяти | ~1 МБ на стек | ~несколько КБ (динамический рост) |\n| Максимальное количество | Тысячи | Миллионы |\n| Стоимость создания | Высокая | Очень низкая |\n| Переключение контекста | Дорогое (ОС) | Дешёвое (JVM) |\n| Привязка к ОС-потоку | 1:1 | M:N (множество на нескольких ОС-потоках) |\n| Стек | Нативная память (фиксированный) | Heap (динамический) |\n\n**Как работают Virtual Threads:**\n\nВиртуальные потоки работают поверх пула **потоков-носителей (carrier threads)**, которые являются обычными Platform Threads. Когда виртуальный поток выполняет блокирующую операцию (IO, `sleep`, `Lock`), JVM автоматически «отсоединяет» (unmount) его от носителя, позволяя последнему выполнять другой виртуальный поток.\n\n\u003Cdetails>\n\u003Csummary>Код: создание и использование виртуальных потоков\u003C\u002Fsummary>\n\n```java\n\u002F\u002F Создание виртуального потока\nThread vThread = Thread.ofVirtual().name(\"my-vthread\").start(() -> {\n    System.out.println(\"Работаю в виртуальном потоке: \" + Thread.currentThread());\n});\n\n\u002F\u002F Фабрика виртуальных потоков\nThreadFactory factory = Thread.ofVirtual().name(\"worker-\", 0).factory();\n\n\u002F\u002F Executor с виртуальными потоками — по одному потоку на задачу\ntry (var executor = Executors.newVirtualThreadPerTaskExecutor()) {\n    List\u003CFuture\u003CString>> futures = new ArrayList\u003C>();\n    for (int i = 0; i \u003C 100_000; i++) {\n        final int taskId = i;\n        futures.add(executor.submit(() -> {\n            Thread.sleep(Duration.ofSeconds(1)); \u002F\u002F не блокирует ОС-поток!\n            return \"Результат задачи \" + taskId;\n        }));\n    }\n    for (Future\u003CString> future : futures) {\n        System.out.println(future.get());\n    }\n}\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Код: HTTP-сервер на виртуальных потоках\u003C\u002Fsummary>\n\n```java\ntry (var executor = Executors.newVirtualThreadPerTaskExecutor()) {\n    ServerSocket serverSocket = new ServerSocket(8080);\n    while (true) {\n        Socket socket = serverSocket.accept();\n        executor.submit(() -> handleRequest(socket));\n    }\n}\n\nvoid handleRequest(Socket socket) {\n    try (var in = socket.getInputStream(); var out = socket.getOutputStream()) {\n        byte[] data = in.readAllBytes();       \u002F\u002F JVM: unmount virtual thread\n        String response = processRequest(data); \u002F\u002F может обращаться к БД, API\n        out.write(response.getBytes());\n    }\n}\n```\n\n\u003C\u002Fdetails>\n\n**Когда использовать Virtual Threads:**\n- IO-bound задачи: HTTP-запросы, обращения к БД, файловый ввод-вывод\n- Задачи с большим количеством одновременных операций ожидания\n- Замена thread-per-request модели в серверных приложениях\n\n**Когда НЕ использовать:**\n- CPU-bound задачи — виртуальные потоки не дают преимущества\n- Задачи, требующие привязки к ОС-потоку (JNI, GPU)\n- Код с `synchronized` и длительными блокировками внутри — происходит **pinning**\n\n**Ключевые факты:**\n- Virtual Threads всегда демоны — они не предотвращают завершение JVM.\n- Нет смысла создавать пул фиксированного размера — паттерн «один поток на задачу» является нормой.\n- Полностью совместимы с существующим API: `Thread`, `ExecutorService`, `Lock`.\n- Стек хранится в куче (heap), растёт\u002Fуменьшается динамически.\n\n**Частые ошибки:**\n- **Pinning** — `synchronized` с блокирующими операциями внутри. Решение — заменить на `ReentrantLock`.\n- Пулирование виртуальных потоков (`newFixedThreadPool`) — антипаттерн.\n- Хранение больших объектов в `ThreadLocal` при миллионах потоков — утечка памяти. Используйте `ScopedValue`.\n\n**Актуальность:** Spring Boot 3.2+ поддерживает через `spring.threads.virtual.enabled=true`. Quarkus, Micronaut, Tomcat, Jetty имеют встроенную поддержку. JDBC-драйверы совместимы с виртуальными потоками.\n\n> **Аналогия:** Platform Threads — это такси: каждая машина (ОС-поток) перевозит одного пассажира (задачу). Можно иметь лишь ограниченный автопарк. Virtual Threads — это автобусная система: один автобус (carrier thread) перевозит множество пассажиров, высаживая одних (unmount при блокировке) и подбирая других (mount при готовности).\n\n> **На собеседовании** ключевой вопрос: «Что такое pinning и как его избежать?» Ответ: pinning — это ситуация, когда виртуальный поток не может быть отсоединён от carrier thread, потому что находится внутри `synchronized`-блока с блокирующей операцией. Решение: заменить `synchronized` на `ReentrantLock`.","","middle",[15,16,17,18,19,20],"Java-21","carrier-threads","Platform-Threads","Project-Loom","Virtual-Threads","concurrency",[],null,{"title":24,"description":25,"ogTitle":26,"ogDescription":27,"keywords":28,"schemaAnswer":35,"featuredSnippetReady":36},"Virtual Threads vs Platform Threads в Java 21 — Project Loom — Gymterview","Virtual Threads — легковесные потоки JVM (Java 21). Миллионы потоков, несколько КБ памяти, автоматический unmount при блокировке. Сравнение с Platform Threads.","Virtual Threads (Java 21) — чем отличаются от Platform Threads?","Virtual Threads управляются JVM, занимают КБ памяти, создаются миллионами. Platform Threads — обёртка над ОС-потоками, ~1 МБ, лимит — тысячи.",[29,30,31,32,33,34],"Virtual Threads Java","Project Loom","виртуальные потоки","Platform Threads","carrier threads","Java 21 потоки","Virtual Threads (Java 21, JEP 444) — легковесные потоки, управляемые JVM, а не ОС. Занимают несколько КБ (vs ~1 МБ), можно создать миллионы (vs тысячи). Работают по модели M:N поверх carrier threads. При блокирующей операции JVM автоматически отсоединяет виртуальный поток от носителя. Подходят для IO-bound задач. Не дают преимущества для CPU-bound. Проблема pinning при synchronized с блокировками внутри.",true]