Spring Boot 3.x 默认支持虚拟线程,WebMvcConfigurer、@RestController等自动运行于虚拟线程;@Async需配VirtualThreadPerTaskExecutor;JDBC/HTTP需适配;监控须用JFR,避免ThreadLocal。

Spring Boot 3.x 原生支持虚拟线程,无需额外配置
Spring Boot 3.0+ 基于 Java 21(或 JDK 21+),默认启用 Project Loom 的虚拟线程特性。只要运行环境是 JDK 21 或更高版本,且未显式禁用,Spring MVC 的 WebMvcConfigurer、@RestController 方法、@Scheduled 任务等默认就在虚拟线程中执行(前提是使用 Tomcat 10.1.12+ / Jetty 12.0.0+ / Undertow 2.3.0+ 等兼容容器)。不需要引入新依赖,也不需手动创建 VirtualThread。 关键前提是:启用 Spring Boot 的虚拟线程模式(默认已开启),可通过以下配置确认或显式声明:
- spring.threads.virtual.enabled=true(Spring Boot 3.2+ 默认为 true)
- 确保 server.tomcat.threads.virtual.enabled=true(Tomcat 场景下)
- 避免在代码中调用 Thread.start() 或显式创建 PlatformThread
用 @Async + 虚拟线程池替代传统线程池
传统 @Async 默认使用 ThreadPoolTaskExecutor(基于 OS 线程),会抵消虚拟线程优势。应切换为虚拟线程感知的执行器:
- 定义 @Bean 返回 TaskExecutor 类型的 VirtualThreadPerTaskExecutor
- 或直接注入 Spring Boot 自动配置的 applicationTaskExecutor(3.2+ 默认已设为虚拟线程执行器)
- 示例:
@Bean
public TaskExecutor applicationTaskExecutor() {
return Executors.newVirtualThreadPerTaskExecutor();
}
数据库与 I/O 操作要适配虚拟线程阻塞模型
虚拟线程在阻塞调用(如 JDBC 查询、HTTP 调用、文件读写)时会自动挂起,不占用 OS 线程 —— 但前提是底层驱动/客户端支持非阻塞或能被 JVM 正确识别为可挂起操作。
- JDBC:推荐使用 HikariCP 5.0+ + PostgreSQL 42.6.0+ / MySQL Connector/J 8.2.0+,它们已适配虚拟线程挂起语义
- HTTP 客户端:RestTemplate 不推荐;改用 WebClient(Reactor 驱动,天然异步)或 HttpClient(JDK 11+ 的 HttpClient.newBuilder().executor(Executors.newVirtualThreadPerTaskExecutor()))
- 避免在虚拟线程中调用 Thread.sleep()、Object.wait()、同步锁竞争严重的方法 —— 这些仍会阻塞虚拟线程调度
监控与调试需关注虚拟线程生命周期
虚拟线程默认不可序列化、无固定名称、不显示在传统线程 dump 中。调试和可观测性需调整方式:
立即学习“Java免费学习笔记(深入)”;
- 使用 jcmd
VM.native_memory summary 或 JFR(Java Flight Recorder)开启 jdk.VirtualThreadSubmitFailed、jdk.VirtualThreadParked 事件 - 日志中可通过 Thread.currentThread().getName() 区分:虚拟线程名形如 "VirtualThread[#123]/runnable"
- 避免依赖线程局部变量(ThreadLocal)传递上下文 —— 虚拟线程频繁创建销毁,易引发内存泄漏;改用 StructuredTaskScope 或 Spring 的 RequestContextHolder(3.2+ 已适配虚拟线程)










