JDK 21虚拟线程需JDK 21+并启用--enable-preview,使用Thread.ofVirtual().start()创建,避免start/join,推荐StructuredTaskScope进行结构化并发管理。

JDK 21 能直接用,但默认不启用虚拟线程、字符串模板等关键新特性——必须显式加参数或改代码,否则你写的 switch 还是老写法,Thread.startVirtualThread() 会抛 UnsupportedOperationException。
Windows/macOS/Linux 安装后必须验证的三件事
装完不等于能用。很多问题不是装错了,而是没验证到位:
-
java -version输出里必须含21.(不是21.0.1+12-LTS这种带 + 号的构建号就可能不对) -
javac -version和java -version版本号要完全一致,否则 IDE 编译通过、运行报错 -
echo $JAVA_HOME(macOS/Linux)或echo %JAVA_HOME%(Windows)必须指向 JDK 21 根目录,且路径中不能有空格或中文(比如C:\Program Files\Java\jdk-21就大概率导致 Maven 构建失败)
虚拟线程跑不起来?先检查 JVM 参数和运行时环境
哪怕 JDK 版本正确,Thread.startVirtualThread() 仍可能直接抛异常。原因很实际:
- 没加
--enable-preview:所有预览特性(如结构化并发、作用域值)必须启动时加这个参数;虚拟线程虽已是正式特性,但某些组合场景仍需它 - IDE 没同步 JDK:IntelliJ 默认用项目 SDK,但 Run Configuration 里 JRE 可能还勾着旧版本;Eclipse 需手动在 Run → Run Configurations → JRE 页签选 “Execution environment: JavaSE-21”
- Spring Boot 版本太低:Spring Boot Executors.newVirtualThreadPerTaskExecutor(),底层仍是普通线程池——必须配
spring.threads.virtual.enabled=true并升级到 3.2+
switch 模式匹配编译失败?注意语法和 target 版本
JDK 21 的 switch 增强不是“写了就能用”,它对编译器和字节码版本有硬性要求:
- 源码必须用
-source 21编译,否则case String s when s.length() > 5 ->这类语法直接报错 - Maven 项目需显式设
<maven.compiler.source>21</maven.compiler.source>,光靠<java.version>21</java.version>不够 - 记录模式(
case Person(String name, int age) p ->)必须配合record类使用,且 record 字段名要和模式变量名一致,否则编译器不认
字符串模板(String Templates)为什么一直提示“preview feature”?
这是目前最常被误以为“装了就能用”的特性——它至今仍是预览功能,连 JDK 21.0.4 都没转正:
- 必须加
--enable-preview启动,且每次运行都要加,IDE 运行配置里漏掉就报java.lang.UnsupportedOperationException: String templates are not supported - 语法不是
"Hello ${name}",而是STR."Hello \{name}"(注意点号和反斜杠) - 模板处理器(如
STR)必须导入java.lang.StringTemplate,且不能自己实现——只有 JDK 自带的处理器才被认可
真正容易被忽略的是:虚拟线程的 Pinning 问题不会报错,只会悄悄拖慢性能;而字符串模板一旦漏掉 --enable-preview,连编译都过不去。新特性不是开关,是需要逐层确认的链路。

















