Java 21 - 并发模型的跃迁
📑 Java 演进系列:总览 | Java 8 | Java 11 | Java 17 | Java 21 | Java 25
Java 21 于 2023 年 9 月 19 日 GA,是继 Java 17 之后的 LTS 版本,按 Oracle 的支持路线图获得长期支持。它的核心主题是并发模型的跃迁:虚拟线程成为正式特性,让"一请求一线程"的阻塞式写法重新可行;记录模式与 switch 模式匹配在语言层面定型,与 Java 17 的 sealed、record 汇合成完整的数据导向编程范式。需要澄清的是:String Templates、Scoped Values、Structured Concurrency、Unnamed Classes 在 Java 21 中均为预览特性,不属于永久语言特性,生产使用需 --enable-preview 并评估后续版本的演进。
虚拟线程
虚拟线程(JEP 444,正式特性)是 JVM 托管的轻量级线程,由调度器挂载到载体平台线程上运行。遇到阻塞 I/O 时,虚拟线程自动让出载体线程,阻塞成本从"占用一个 OS 线程"降为"一次栈帧切换",单机可轻松支撑百万级并发任务。
1 | |
使用要点:虚拟线程适合阻塞式 I/O 密集任务,CPU 密集任务仍用平台线程池;避免在虚拟线程中长期持有 synchronized 锁(Java 24 的 JEP 491 才消除其钉住问题),改用 ReentrantLock;不要池化虚拟线程,直接每任务创建。深入实践参见虚拟线程专题。
记录模式
记录模式(JEP 440,正式特性)允许 instanceof 与 switch 直接解构 record 的组件,并支持嵌套——一条模式语句即可拆出多层字段。它让 record 从"声明数据的载体"进一步成为"逻辑分支的依据"。
1 | |
模式变量(如 x1、y1)在匹配成功后自动可用,替代了传统的"instanceof 判断 + 强制转型 + 逐字段取值"样板。嵌套解构是 Java 21 的关键增量:Line(Point(...), Point(...)) 在一条模式中同时匹配外层与内层。
switch 模式匹配
switch 模式匹配(JEP 441,正式特性)让 case 支持类型模式与记录模式,且当 switch 目标是 sealed 层级时编译器可做穷尽性检查——分支覆盖所有许可子类即可省略 default,新增子类时编译期立即报错。
1 | |
case null 分支可直接处理空值而不再抛出 NullPointerException;case Circle c when c.radius() > 100 这类带条件的守卫分支也是同一语法的自然组成。配合 sealed 类型,"封闭集合 + 分支穷尽"构成了类型安全的数据处理闭环。
有序集合
有序集合(JEP 431,正式特性)为"具有确定遍历顺序"的集合补齐了统一 API:SequencedCollection 及其变体提供 getFirst()、getLast()、reversed()、addFirst()、addLast()。此前获取 List 末元素要写 list.get(list.size() - 1),LinkedHashSet 两端访问更是没有标准途径。
1 | |
reversed() 返回逆序视图,对底层集合的修改会同步反映。迁移时注意接口层面的影响:自定义集合类若实现 List,会间接继承新的 default 方法,覆盖它们以保持语义一致。
外部函数与内存 API(预览)
外部函数与内存 API(FFM,JEP 443)在 Java 21 处于第三次预览,需 --enable-preview 编译运行。它以 MemorySegment、Arena、Linker 替代 JNI 与 sun.misc.Unsafe:堆外内存分配有确定的生命周期(Arena 关闭即释放),访问受边界检查保护。
1 | |
1 | |
Arena 关闭后段不可再访问,取代了 Cleaner 兜底释放的脆弱模式。该 API 直到 Java 22 才定稿,生产依赖需锁定预览语义并跟踪后续版本的签名变化。
分代 ZGC(HotSpot/JDK)
分代 ZGC(JEP 439)是 HotSpot 虚拟机的垃圾回收器实现改进,属于 JDK 发行版的运行时能力,而非 Java SE 语言或 API 保证。ZGC 引入分代假设——多数对象朝生夕死,为年轻代单独回收后,吞吐与内存占用同时改善,且保持亚毫秒级停顿的目标不变。
1 | |
适用于大堆、低延迟的服务端负载。是否可用取决于具体 JDK 发行版与 GC 选择,不应写入依赖 Java SE 规范的代码假设。
常用特性总结
- 虚拟线程:
Executors.newVirtualThreadPerTaskExecutor()处理阻塞 I/O 高并发,不池化、避免长持synchronized。 - 记录模式:
instanceof Line(Point(var x1, var y1), ...)嵌套解构,消除强制转型样板。 - switch 模式匹配:sealed 层级上的类型模式分支,编译器保证穷尽性,支持
null分支与守卫条件。 - 有序集合:
getFirst()、getLast()、reversed()统一有序集合两端访问。 - FFM API(预览):
Arena+MemorySegment管理 Java 堆外内存,需--enable-preview。 - 分代 ZGC(HotSpot/JDK):
-XX:+UseZGC -XX:+ZGenerational获得分代低延迟回收。
迁移与兼容性
从 Java 17 升级到 Java 21 通常平稳:语言与 API 变化以新增为主,默认字符集等破坏性调整已在 Java 18 完成。重点检查项:升级前确认第三方库与框架(尤其 Spring、Netty 系)声明支持 Java 21;synchronized 长期持锁的代码迁入虚拟线程前先改 ReentrantLock;实现自定义集合类时审计新增的 SequencedCollection default 方法;不建议在模块路径上携带依赖 FFM 预览签名的库,其 API 在 Java 22 后有变动。生产采用预览特性前必须接受后续版本可能不兼容的成本,String Templates 甚至在 Java 23 被移除重设计——这是"预览不等于最终特性"的直接例证。





