1. 什么是虚拟线程
虚拟线程是 JDK 19 引入预览(Preview),JDK 21 正式 GA(General Availability) 的重大特性之一。
它属于 Project Loom,旨在解决 Java 传统线程(基于 OS 内核线程)的高内存和高调度开销问题。
- 传统线程:每个线程绑定一个操作系统线程(1:1 映射),受限于内存和内核调度。一般几千个就可能瓶颈。
- 虚拟线程:由 JVM 管理和调度,不再与操作系统线程一一绑定,而是 成千上万的虚拟线程复用少量 OS 线程(Carrier Threads)。
可以理解为:
- 传统线程 = “笨重卡车”
- 虚拟线程 = “轻便小车”,几百万个也没问题。
2. 虚拟线程的特点
- 极轻量
一个虚拟线程的内存消耗只有几 KB,可以创建数百万个。 - 无需线程池
在 JDK 21 中,虚拟线程基本替代了传统的ThreadPoolExecutor模式,不需要为了避免线程爆炸而写复杂的线程池代码。 - 兼容阻塞式 API
虚拟线程支持Blocking I/O,调用Socket、JDBC等阻塞 API 时不会阻塞底层的 OS 线程,而是把虚拟线程挂起,JVM 调度其它虚拟线程继续运行。 - 调度器是 ForkJoinPool(默认)
虚拟线程默认由一个全局的ForkJoinPool作为调度器(类似 Go 的调度模型)。
3. 使用示例(JDK 21)
创建虚拟线程
public class VirtualThreadDemo {
public static void main(String[] args) throws InterruptedException {
// 方式1:直接启动虚拟线程
Thread vThread = Thread.ofVirtual().start(() -> {
System.out.println("Hello from Virtual Thread: " + Thread.currentThread());
});
vThread.join();
// 方式2:ExecutorService 管理虚拟线程
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < 10; i++) {
int taskId = i;
executor.submit(() -> {
System.out.println("Task " + taskId + " running in " + Thread.currentThread());
Thread.sleep(1000); // 不会阻塞底层 OS 线程
return taskId;
});
}
}
}
}
输出类似:
Task 0 running in VirtualThread[#25]/runnable
Task 1 running in VirtualThread[#26]/runnable
...
4. 使用场景
- 高并发 IO 密集型系统(Web 服务、RPC 调用、消息处理)
- 数据库/JDBC 调用(无需切换成异步驱动,也能提升性能)
- 爬虫、任务调度系统(百万级任务并发)
不太适合:
- 大量 CPU 密集型任务(会占用调度器 OS 线程,虚拟线程失去意义)。
5. 与其他异步方案对比
| 技术 | 模型 | 缺点 | 优点 |
|---|---|---|---|
| 线程池 + Future | 传统阻塞线程 | 线程数有限,复杂度高 | 简单、成熟 |
| CompletableFuture | 回调 + 线程池 | 可读性差,回调地狱 | 适合并行计算 |
| Reactive (Reactor/ RxJava) | 事件驱动(响应式) | 学习曲线陡峭,生态不统一 | 高性能 IO |
| 虚拟线程 (JDK21) | 阻塞式写法 + 虚拟调度 | 需要 JDK21+ | 性能高,开发简单,未来趋势 |
虚拟线程 = 阻塞式 API 的“异步化”升级方案,不需要学习新编程模型。
6. 总结
- JDK 21 的 虚拟线程 = “轻量级线程”,让 Java 程序可轻松创建百万级并发。
- 对 IO 密集型应用是颠覆性提升,几乎消除了传统“线程池 + 回调”的复杂性。
- 编程模型保持同步写法,易于迁移和维护。
584

被折叠的 条评论
为什么被折叠?



