平台线程 vs 虚拟线程 在 Java
发布: (2026年2月4日 GMT+8 02:07)
5 min read
原文: Dev.to
Source: Dev.to
平台线程
在 Java 中,经典的线程模型称为 平台线程。这些是直接由操作系统支持的传统线程。
Thread thread = new Thread(() -> {
doWork();
});
thread.start(); // Starts a new platform thread
起初感觉很强大——你得到真正的并行工作和实际的多任务。然而,当你:
- 创建太多线程 → 应用程序变慢。
- 处理成千上万的请求 → 线程池耗尽。
- 执行阻塞 I/O → 线程在等待外部操作时处于空闲状态。
为什么? 因为平台线程直接映射到 OS 线程:
- 一个 Java 线程 = 一个 OS 线程。
- OS 线程代价高(大栈、调度开销)。
于是,开发者会采用:
- 固定大小的线程池。
- 异步 API。
- 响应式编程。
- 复杂的执行模型。
这些变通方案并非出于需求,而是平台线程可扩展性限制所致。
核心问题
在 I/O 操作期间,线程:
- 不执行计算。
- 不使用 CPU。
- 仅等待外部操作完成。
但它占用了稀缺的 OS 资源。这正是 虚拟线程 发挥作用的地方。
虚拟线程 — 轻量且可扩展
虚拟线程是由 JVM 管理的轻量线程,能够在不产生 OS 线程开销的情况下并发数百万任务。
Thread thread = Thread.startVirtualThread(() -> {
doWork();
});
- 与平台线程相同的编程模型和阻塞风格。
- 由 JVM 创建和调度,而不是永久绑定到 OS 线程。
- 与平台线程相比极其廉价。
实际发生的事情
- 运行时:虚拟线程被挂载到一个 载体(平台)线程上。
- 阻塞时:虚拟线程被停放,释放载体线程。
- 解除阻塞时:它在任意可用的载体线程上恢复执行。
因此,仅阻塞的是虚拟线程本身,而不是底层的 OS 线程。这消除了平台线程的可扩展性瓶颈:
- 阻塞 I/O 不再浪费 OS 线程。
- 线程池不再是硬性限制。
- 简单的阻塞代码可以扩展到大规模并发。
虚拟线程并没有消除阻塞,它消除了阻塞的成本。
它们的区别
关键区别在于每种线程处理阻塞的方式:
| 方面 | 平台线程 | 虚拟线程 |
|---|---|---|
| 映射 | 与 OS 线程一对一 | 多个虚拟线程共享载体线程 |
| 阻塞影响 | 阻塞一个 OS 线程 | 只阻塞虚拟线程本身 |
| 创建成本 | 高(栈、调度) | 低(JVM 管理) |
| 可扩展性 | 受 OS 资源限制 | 可处理数百万并发任务 |
何时使用哪种线程更合适
何时使用虚拟线程
- 工作负载以 I/O 为主(例如处理大量并发请求)。
- 需要等待数据库、外部 API 或文件系统。
- 构建 Web 服务器、API 或微服务。
- 想要使用简单的阻塞代码且仍能实现可扩展性。
何时使用平台线程
- 工作负载以 CPU 为主。
- 需要与操作系统进行紧密交互。
- 涉及线程绑定、原生调用或其他低层操作。
实际指南
等待时使用虚拟线程,计算时使用平台线程。
这条规则覆盖了大多数真实场景的决策。
虚拟线程并不会让 Java 更快;它让你能够编写简单的阻塞代码,而不必担心线程池的限制。