虚拟线程是jvm层m:n调度的轻量级线程,不绑定os线程、栈内存按需堆分配、切换开销纳秒级;适用于io密集场景,不适用于cpu密集任务。

虚拟线程不是“继承 Thread 的轻量版”,而是彻底绕开了操作系统线程的物理约束——它不依赖 pthread_create,不占用固定栈内存,也不触发内核态切换。所谓“颠覆”,本质是调度层级和资源模型的双重重构。
不再绑定 OS 线程:从 1:1 到 M:N 的根本切换
传统 new Thread() 创建的是平台线程(Platform Thread),每个实例强绑定一个 OS 线程,生命周期、栈空间、上下文全由内核管理。而虚拟线程运行在 JVM 自研的调度器(默认 ForkJoinPool)之上,多个虚拟线程动态挂载(mount)到少量载体线程(Carrier Thread)上执行:
- 一个载体线程可同时服务成百上千个虚拟线程
- 虚拟线程阻塞(如
SocketChannel.read()、Object.wait()、Thread.sleep())时,JVM 自动将其卸载(unmount),载体线程立刻切换执行其他就绪虚拟线程 - 无需内核介入,切换开销从微秒级降至纳秒级
栈内存从“预分配”变为“按需堆分配”
平台线程默认预留 1MB 栈空间(Linux x64),哪怕只用几 KB,这部分内存全程锁定且不可回收;虚拟线程的栈帧则保存在 Java 堆中,初始仅几百字节,随方法调用深度动态扩容,返回后自动缩容或 GC 回收:
- 创建 10 万个虚拟线程,堆内存增量通常不到 100MB
- 同等数量的平台线程需至少 10GB 栈内存,远超单机承载能力
- 栈溢出(StackOverflowError)仍可能发生,但阈值由 JVM 动态控制,与 OS 无关
API 兼容但语义重定义:Thread 类仍是入口,行为已重构
Thread 类本身没有被废弃,而是被扩展为统一抽象层:
-
Thread.startVirtualThread(Runnable)或Thread.ofVirtual().start(...)明确声明使用虚拟线程调度 -
Thread.currentThread().isVirtual()可运行时判断线程类型 - 所有同步原语(
synchronized、wait/notify、Lock)对虚拟线程完全有效,但底层实现已替换为用户态协作式挂起 - 传统线程池(如
FixedThreadPool)不应包装虚拟线程——这会抵消全部优势,甚至引发调度死锁
真正落地的关键:只在 IO 密集场景启用,避开 CPU 密集误区
虚拟线程不是万能加速器。它的优势集中在“高并发 + 高等待率”场景:
- ✅ 推荐:HTTP 请求处理、数据库查询、RPC 调用、消息消费
- ❌ 不推荐:图像渲染、加密计算、密集循环等纯 CPU 任务——此时平台线程 + 合理并行度更高效
- ⚠️ 注意:若虚拟线程内部频繁执行
Thread.yield()或长时间空转,会导致载体线程饥饿,应改用结构化并发(StructuredTaskScope)做显式编排










