理解虚拟线程
为什么会有虚拟线程 JDK 21 把虚拟线程带进了 Java 标准库。它并不是要取代平台线程,也不是让 CPU 突然变快;它主要解决的是另一类问题:服务里有大量任务在等网络、数据库或其他外部资源时,怎样不让“等待”长期占住宝贵的操作系统线程。 先从我们熟悉的线程模型说起。传统 Java 平台线程与操作系统线程紧密对应。写一个线程很简单,但线程的栈、调度和上下文切换都要消耗系统资源。线程数量一旦上去,系统很可能不是在处理业务,而是在管理线程本身。 创建和销毁: 平台线程的生命周期需要操作系统参与。它并非不能创建很多,但高频创建、销毁的成本通常不适合直接忽略。 内存占用: 线程栈大小由 JVM 参数、操作系统和架构共同决定。 例如: 某些环境设置了 -Xss1m 后,每条平台线程的栈上限可能接近 1MB;数万个线程的栈预留就会带来明显压力。具体数值必须以线上 JVM 配置和压测为准。 调度成本: 操作系统负责平台线程的调度。线程远多于 CPU 核心、并且频繁切换时,保存和恢复上下文、缓存失效等成本会逐渐显现。 表达方式: 因此,过去的服务通常会用线程池把并发任务排队。这很实用,但线程池既在复用线程,也常常不经意地承担了“限制并发”的职责。 虚拟线程的出发点很朴素:如果一个任务大部分时间都在等结果,那就不该为了这段等待一直占着一条 OS 线程。它让我们可以继续按“一项任务一条线程”的方式组织代码,只是这条线程不再必须从头到尾绑定同一条平台线程。 虚拟线程改变了什么 虚拟线程仍然是 java.lang.Thread ,业务代码里依然可以使用熟悉的顺序式写法。变化发生在运行时:JVM 可以把大量虚拟线程映射到较少的平台线程上执行,并在合适的阻塞点把虚拟线程暂时卸载。 创建成本更低: 虚拟线程由 JVM 管理,通常比平台线程更轻,适合为大量独立、短生命周期的任务分别创建线程。 栈按需增长: 它的初始开销通常显著低于平台线程,但并不是固定“几 KB”。调用栈、局部变量、任务对象和堆内存都会影响实际占用。 例如: 十万个主要在等待 HTTP 响应的任务,可能适合用十万个虚拟线程表达;如果每个任务都持有大对象,先碰到的仍可能是堆内存上限。 等待不必占住载体线程: 在 JDK 支持的阻塞操作中,虚拟线程可以被挂起,载体线程转而运行其他任务。对 I/O 密集型服...