结论先行:对典型的「高并发 IO 密集」业务,虚拟线程的收益是真实的,但不是魔法。我们的网关服务在压测中 P99 延迟下降约 18%,内存占用下降 30%,前提是老老实实改掉了所有线程池内的阻塞假设。
升级路径
- Spring Boot 升级到 3.2+,spring.threads.virtual.enabled=true 一行开启。
- 排查 synchronized 长代码块:Pin 问题会让虚拟线程退化,必要时换成 ReentrantLock。
- 删除大部分业务线程池:Executors.newVirtualThreadPerTaskExecutor() 取代固定池。
- 压测对比:相同流量下吞吐、P99、内存三项指标。
遇到的两个坑
一是老代码里一个 synchronized 的序列化工具类在高并发下大量 pin,表现为延迟毛刺,换锁后消失。二是 ThreadLocal 滥用的链路追踪组件在百万级虚拟线程下内存暴涨,改用 ScopedValue 语义的上下文传递才解决。
虚拟线程改变了「阻塞很贵」的默认假设,但改变不了「共享可变状态很危险」的事实。
我的建议:新项目直接上 JDK 21;存量项目如果瓶颈在 IO 等待而非 CPU,值得排期升级,但要把 pin 排查和 ThreadLocal 治理列入工作量,别指望一行配置解决所有问题。