JDK21来了!附重要更新说明
JDK21 计划23年9月19日正式发布,虽然一直以来都是“版本随便出,换 8 算我输”,但这么多年这么多版本的折腾,如果说之前的 LTS版本JDK17你还觉得不香,那 JDK21还是有必要关注一下,因为会有一批重要更新发布到生产环境中,特别是千呼万唤的虚拟线程,虽然说这东西我感觉不需要的用不到,需要的早都转go了,哈哈,但作为近几年JDK一个“重大”的更新,在实际开发应用中还是是有很大价值的。所以这篇文章主要提取了这次更新中个人感觉比较有价值的几点做个基本的介绍,想要尝鲜的同学可以看下。
Visual Threads (虚拟线程) -JEP 444
先看下官方对虚拟线程(Visual Threads)描述:
Today, every instance of
java.lang.Threadin the JDK is a platform thread. A platform thread runs Java code on an underlying OS thread and captures the OS thread for the code's entire lifetime. The number of platform threads is limited to the number of OS threads.A virtual thread is an instance of
java.lang.Threadthat runs Java code on an underlying OS thread but does not capture the OS thread for the code's entire lifetime. This means that many virtual threads can run their Java code on the same OS thread, effectively sharing it. While a platform thread monopolizes a precious OS thread, a virtual thread does not. The number of virtual threads can be much larger than the number of OS threads.Virtual threads are a lightweight implementation of threads that is provided by the JDK rather than the OS. They are a form of user-mode threads, which have been successful in other multithreaded languages (e.g., goroutines in Go and processes in Erlang). User-mode threads even featured as so-called "green threads" in early versions of Java, when OS threads were not yet mature and widespread. However, Java's green threads all shared one OS thread (M:1 scheduling) and were eventually outperformed by platform threads, implemented as wrappers for OS threads (1:1 scheduling). Virtual threads employ M:N scheduling, where a large number (M) of virtual threads is scheduled to run on a smaller number (N) of OS threads.
总结下就是之前java中的线程是“platform thread”即平台线程,它由操作系统线程为基础,按照1:1的模式调度,这导致线程的创建与执行都是很耗资源的,同时数量也受系统的约束;但新的虚拟线程则是由JDK提供,你可以把它看作是在平台线程基础上创建的“一批”线程,它们有效地共享所属的平台线程也就是操作系统线程的资源,从而提升系统利用率,并不受数量限制。
目标描述:
1、Enable server applications written in the simple thread-per-request style to scale with near-optimal hardware utilization.
可以每个请求开启一个虚拟线程,实现简单直接的同时可以最大程度的提升硬件利用率;
2、Enable existing code that uses the
java.lang.ThreadAPI to adopt virtual threads with minimal change.之前的多线程实现代码可以在较小的改动下完成向虚拟线程的迁移;
3、Enable easy troubleshooting, debugging, and profiling of virtual threads with existing JDK tools.
使用现有JDK工具可以完成虚拟线程的代码调试、分析与问题定位;
说白了就是现在我们不用怎么改代码就可以创建一个轻量级的虚拟线程,实现简单同时还能够充分发挥硬件性能。
一个简单的代码示例
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10000).forEach(i -> {
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return i;
});
});
} // executor.close() is called implicitly, and waits
SequencedCollection Interface(顺序集合 接口)
兄弟们,作为一个天天CRUD,CPU跑不满20%的程序员, 相比上面的虚拟线程,这次关于集合类接口的更新我感觉更实在一些
JDK21中我们常用的Set、List、Deque与Map集合类分别继承实现了SequencedCollection、 SequencedMap 接口,为我们执行一些顺序性操作比如获取头尾值提供了各类接口方法
继承关系如下图所示:

接口定义如下
interface SequencedCollection<E> extends Collection<E> {
// new method
SequencedCollection<E> reversed();
// methods promoted from Deque
void addFirst(E);
void addLast(E);
E getFirst();
E getLast();
E removeFirst();
E removeLast();
}
interface SequencedSet<E> extends Set<E>, SequencedCollection<E> {
SequencedSet<E> reversed(); // covariant override
}
interface SequencedMap<K,V> extends Map<K,V> {
// new methods
SequencedMap<K,V> reversed();
SequencedSet<K> sequencedKeySet();
SequencedCollection<V> sequencedValues();
SequencedSet<Entry<K,V>> sequencedEntrySet();
V putFirst(K, V);
V putLast(K, V);
// methods promoted from NavigableMap
Entry<K, V> firstEntry();
Entry<K, V> lastEntry();
Entry<K, V> pollFirstEntry();
Entry<K, V> pollLastEntry();
}
Record Patterns (记录模式)-JEP 440
这个更新主要简化了类型判断与赋值的使用,类型判断后无需显式强制转换且如果模式匹配,变量被初始化为要匹配的模板值, 这个说起来比较拗口,结合代码大家理解下,我感觉还是挺有用的,这里我把JDK8 JDK17 JDK21 的实现进行一个对比,大家就明白了。
// As of Java 8
record Point(int x, int y) {}
static void printSum(Object obj) {
if (obj instanceof Point) {
Point p = (Point) obj;
int x = p.x();
int y = p.y();
System.out.println(x+y);
}
}
// As of Java 16
record Point(int x, int y) {}
static void printSum(Object obj) {
if (obj instanceof Point p) {
int x = p.x();
int y = p.y();
System.out.println(x+y);
}
}
// As of Java 21
static void printSum(Object obj) {
if (obj instanceof Point(int x, int y)) {
System.out.println(x+y);
}
}
Pattern Matching for switch (switch模式匹配) – JEP 441
switch 的模式匹配可以与Record Patterns结合使用 允许在任何对象上制定 switch 语句和表达式。看一下代码例子:
static String formatterPatternSwitch(Object obj) {
return switch (obj) {
case Integer i -> String.format("int %d", i);
case Long l -> String.format("long %d", l);
case Double d -> String.format("double %f", d);
case String s -> String.format("String %s", s);
case Position(int x, int y) -> String.format("String %s,String %s", x,y);
default -> obj.toString();
};
}
同时当编译器判断所有分支都已涵盖时,switch不再需要分支default,如下面的代码
void flyJava21(Direction direction) {
switch (direction) {
case CompassDirection.NORTH -> System.out.println("Flying north");
case CompassDirection.SOUTH -> System.out.println("Flying south");
case CompassDirection.EAST -> System.out.println("Flying east");
case CompassDirection.WEST -> System.out.println("Flying west");
case VerticalDirection.UP -> System.out.println("Gaining altitude");
case VerticalDirection.DOWN -> System.out.println("Losing altitude");
}
}
Generational ZGC(分代式 ZGC) -JEP 439
主要是增加了对分代的支持,提高垃圾回收的性能,看下整体描述
To ensure a smooth succession, we will initially make Generational ZGC available alongside non-generational ZGC. The
-XX:+UseZGCcommand-line option will select non-generational ZGC; to select Generational ZGC, add the-XX:+ZGenerationaloption:
使用命令行选项 -XX:+UseZGC 将选择非分代式 ZGC;要选择分代式 ZGC,需要添加 -XX:+ZGenerational 选项。
$ java -XX:+UseZGC -XX:+ZGenerational ...
In a future release we intend to make Generational ZGC the default, at which point
-XX:-ZGenerationalwill select non-generational ZGC. In an even later release we intend to remove non-generational ZGC, at which point theZGenerationaloption will become obsolete.
总结就是当前版本中如果想使用ZGC,命令行选项增加 -XX:+UseZGC,但默认是非分代式GC;要使用分代式ZGC ,需要改为 $ java -XX:+UseZGC -XX:+ZGenerational ,而在后续的版本中会默认改为分代GC。
以上就是JDK21版本中我感觉一些有价值的更新,如果大家希望能够更进一步的了解还是要去官网https://openjdk.org/projects/jdk/21/ 自行查看,并在发布之后在使用中实际验证。
之所以有这次总结,主要还是有感于java近年来受到其他各类语言的冲击,颇有垂垂老矣的感觉,让我这个C#出身的javaer又想起了一段不好的回忆,哈哈,所以看看这次的更新是否能给点力, 当前java语言的下行趋势也可以说是国内IT行业兴衰起伏的一个侧面写照,当然作为一个提供生产力的编程语言,围绕java建立起的整个完整、稳定、强大的生态仍然会在它适合的领域起到重要的作用,这是一时半会无法改变的,但你指望靠它干到退休估计连收了学费的培训机构也不敢这样说,程序员的职业寿命从来不是某种编程语言决定的。最后我还是想说入行的菜鸟才纠结于语言优劣,成熟老手知道这早有定论,让我们大声喊出:
"PHP是最好的语言"
这不是玩梗,因为从某种角度上讲:
"生产力才是决定语言生死的关键"
- 参考资料:https://openjdk.org/projects/jdk/21/
关注微信公众号,查看更多技术文章。

JDK21来了!附重要更新说明的更多相关文章
- Oracle查询索引碎片及数据表空间使用情况
--检查索引碎片情况,只能对单个表进行分析. --需要注意块的大小.索引的pctfree的值的大小.rowid的长度的不同,根据不同的情况修改相应的值 select index_name, c.NMB ...
- PSS下载助手(PSX Download Helper)1.7.6.1发布
新增自动查找本地替换文件,让替换大法也更简单的计划…… 使用方法很简单,首先进入设置勾选“自动查找替换文件”,然后点击“选择目录”,最后保存设置即可.将文件下载至你选择的目录中,然后再次在主机/掌机端 ...
- CYQ.Data 开源数据层框架 官方下载
CYQData 数据框架 介绍: CYQ.Data 是一款操作数据库用的数据框架:安全稳定.简洁易用.功能强大.性能优越.内置支持多数据库.多语言.RSS.AOP.事务等功能. 使用本框架进行开发,入 ...
- 【开源毕设】一款精美的家校互动APP分享——爱吖校推 [你关注的,我们才推](持续开源更新3)附高效动态压缩Bitmap
一.写在前面 爱吖校推如同它的名字一样,是一款校园类信息推送交流平台,这么多的家校互动类软件,你选择了我,这是我的幸运.从第一次在博客园上写博客到现在,我一次一次地提高博文的质量和代码的可读性,都是为 ...
- Red Gate系列之五 .NET Reflector 7.6.1.824 Edition .NET程序反编译神器(附插件安装教程2012-10-13更新) 完全破解+使用教程
原文:Red Gate系列之五 .NET Reflector 7.6.1.824 Edition .NET程序反编译神器(附插件安装教程2012-10-13更新) 完全破解+使用教程 Red Gate ...
- (转) Mac下面的SecureCRT(附破解方案) 更新到最新的7.3.7
Mac下面的SecureCRT(附破解方案) 更新到最新的7.3.7 转自 http://blog.csdn.net/skykingf/article/details/17450561 http:// ...
- PYTHON爬虫实战_垃圾佬闲鱼爬虫转转爬虫数据整合自用二手急速响应捡垃圾平台_3(附源码持续更新)
说明 文章首发于HURUWO的博客小站,本平台做同步备份发布. 如有浏览或访问异常图片加载失败或者相关疑问可前往原博客下评论浏览. 原文链接 PYTHON爬虫实战_垃圾佬闲鱼爬虫转转爬虫数据整合自用二 ...
- 神技!微信小程序(应用号)抢先入门教程(附最新案例DEMO-豆瓣电影)持续更新
微信小程序 Demo(豆瓣电影) 由于时间的关系,没有办法写一个完整的说明,后续配合一些视频资料,请持续关注 官方文档:https://mp.weixin.qq.com/debug/wxadoc/de ...
- 用友ERP-U8最新破解(再次更新版本,附安装过程中的解决办法)
新版用友u8.70下载地址:http://ftp.shangyuchem.com/应用软件/用友ERP-U8管理软件(8.70版).rar 准备好安装环境,因为需要SQLSERVER和IIS支持,而个 ...
- 学习图像算法阶段性总结 (附一键修图Demo) 2016.04.19更新demo
今天特别感慨,自己从决定研究图像处理,势必要做出一键修图算法. 经历了,三个多月的书籍积累,三个多月的算法调整以及优化. 人是一种奇怪的动物,当你做不到的时候,你以为做到了,自己会感觉很爽,很有成就感 ...
随机推荐
- 烂怂if-else代码优化方案
0.问题概述 代码可读性是衡量代码质量的重要标准,可读性也是可维护性.可扩展性的保证,因为代码是连接程序员和机器的中间桥梁,要对双边友好.Quora 上有一个帖子: "What are so ...
- vue3实现H5网页录音并上传(mp3、wav)兼容Android、iOS和PC端
使用 Recorder插件 可以在HTML5网页中进行录音,录音完成后得到blob文件对象,然后将blob上传到服务器:项目使用的vue3.0版本(这个插件同时支持vue2.0.也支持uniapp,很 ...
- 【技术积累】Java中的泛型【一】
泛型是什么 Java中的泛型是一种能够让用户在编写代码时避免使用明确的类型而进行类型参数化的机制.Java中的泛型可以让编程者在代码编写时不必关心具体类型,只用关心类型之间的关系和相互转换,从而在编写 ...
- C#.NET CORE .NET6 RSA 私钥签名 公钥验签(验证签名) ver:20230614
C#.NET CORE .NET6 RSA 私钥签名 公钥验签(验证签名) ver:20230614 环境说明: .NET CORE 版本:.NET 6 . .NET CORE 对于RSA的支持: 1 ...
- C#/.Net的多播委托到底是啥?彻底剖析下
前言 委托在.Net里面被托管代码封装了之后,看起来似乎有些复杂.但是实际上委托即是函数指针,而多播委托,即是函数指针链.本篇来只涉及底层的逻辑,慎入. 概括 1.示例代码 public delega ...
- 【webpack系列】从基础配置到掌握进阶用法
前言 本篇文章将介绍一些webpack的进阶用法,演示内容继承自上一篇文章的内容,所以没看过上一篇文章的建议先学习上一篇内容再阅读此篇内容,会更有利于此篇的学习- 文件指纹 文件指纹指的是打包输出的文 ...
- 【Docker】部署Redis
1.下载镜像 #下载最新版Redis镜像 (其实此命令就等同于 : docker pull redis:latest ) docker pull redis # 下载指定版本的Redis镜像 (xxx ...
- 2023-07-13:如果你熟悉 Shell 编程,那么一定了解过花括号展开,它可以用来生成任意字符串。 花括号展开的表达式可以看作一个由 花括号、逗号 和 小写英文字母 组成的字符串 定义下面几条语
2023-07-13:如果你熟悉 Shell 编程,那么一定了解过花括号展开,它可以用来生成任意字符串. 花括号展开的表达式可以看作一个由 花括号.逗号 和 小写英文字母 组成的字符串 定义下面几条语 ...
- 【环境搭建】docker+nginx部署PHP
目的 使用docker容器完成nginx的安装以及部署PHP网页 步骤 一. 安装nginx 1. 拉取Nginx镜像 docker pull nginx //拉取镜像 docker images / ...
- Mysql高级2-SQL性能分析
一.SQL执行频率 MySQL客户端 连接成功后,通过show [session | global] status 命令可以提供服务器状态信息,通过如下指令,可以查看当前数据库的insert,upda ...