Java 20 新功能介绍

➜ bin pwd
/Users/darcy/develop/jdk-20.0.1.jdk/Contents/Home/bin
➜ bin ./java -version
openjdk version "20.0.1" 2023-04-18
OpenJDK Runtime Environment (build 20.0.1+9-29)
OpenJDK 64-Bit Server VM (build 20.0.1+9-29, mixed mode, sharing)
Java 20 共带来 7 个新特性功能,其中三个是孵化提案,孵化也就是说尚在征求意见阶段,未来可能会删除此功能。
| JEP | 描述 | 分类 |
|---|---|---|
| 429 | 作用域值(孵化器) | Project Loom,Java 开发相关 |
| 432 | Record 模式匹配(第二次预览) | Project Amber,新的语言特性 |
| 433 | switch 的模式匹配(第四次预览) | Project Amber,新的语言特性 |
| 434 | 外部函数和内存 API(第二个预览版) | Project Panama,非 Java 库 |
| 436 | 虚拟线程(第二个预览版) | Project Loom,Java 开发相关 |
| 437 | 结构化并发(第二孵化器) | Project Loom,Java 开发相关 |
| 438 | Vector API(第五孵化器) | Project Panama,非 Java 库 |
JEP:JDK Enhancement Proposal,JDK 增强建议,或者叫 Java 未来发展建议。
JDK 20 不是长期支持 (LTS) 版本,因此它只会在六个月后被 JDK 21 取代之前收到更新。JDK 17( 2021 年 9 月 14 日发布)是 Java 的最新 LTS 版本。Oracle 宣布计划将 LTS 版本之间的时间从三年缩短到两年,因此 JDK 21(2023 年 9 月)计划成为下一个LTS。
Java 20 安装
Java 20 OpenJDK 下载:https://jdk.java.net/19/
Java 20 OpenJDK 文档:https://openjdk.java.net/projects/jdk/20/
Java 20 OracleJDK 下载:Oracle JDK 20 Archive Downloads
# 此文中示例代码运行都在 Java 20 环境下使用命令
➜ src $ /jdk-20.0.1.jdk/Contents/Home/bin/java --version
openjdk 20.0.1 2023-04-18
OpenJDK Runtime Environment (build 20.0.1+9-29)
OpenJDK 64-Bit Server VM (build 20.0.1+9-29, mixed mode, sharing)
➜ src $ /jdk-20.0.1.jdk/Contents/Home/bin/java --add-modules jdk.incubator.concurrent Xxx.java
WARNING: Using incubator modules: jdk.incubator.concurrent
hello wdbyte
没有信息
JEP 429: Scoped Value
在线程之间共享变量不是一件简单的事,可以使用 ThreadLocal 来保存当前线程变量,但是需要手动清理,开发者常常忘记,且变量不能被子线程继承;而使用 InheritableThreadLocal 共享信息可以被子线程继承,但是数据会拷贝多份,占用更多内存。
引入Scoped values,允许在线程内和线程间共享不可变数据,这比线程局部变量更加方便,尤其是在使用大量虚拟线程时。这提高了易用性、可理解性、健壮性以及性能。不过这是一个正在孵化的 API,未来可能会被删除。
scoped values 有下面几个目标:
- 易用性——提供一个编程模型来在线程内和子线程之间共享数据,从而简化数据流的推理。
- 可理解性——使共享数据的生命周期从代码的句法结构中可见。
- 稳健性——确保调用者共享的数据只能由合法的被调用者检索。
- 性能——将共享数据视为不可变的,以便允许大量线程共享,并启用运行时优化。
例子
如果每个请求都是用一个单独的线程来处理,现在需要接受一个请求,然后根据不同身份访问数据库,那么我们可以用传递参数的方式,直接把身份信息在调用访问数据库方法时传递过去。如果不这么做,那么就要使用 ThreadLocal 来共享变量了。
Thread 1 Thread 2
-------- --------
8. 数据库 - 开始查询 () 8. throw new InvalidPrincipalException()
7. 数据库 - 开始访问 () <---+ 7. 数据库 - 开始访问 () <---+
... | ... |
... 身份(管理员) ... 身份(访客)
2. 开始处理(..) | 2. 开始处理(..) |
1. 收到请求(..) -----------+ 1. 收到请求(..) -----------+
示意代码:
class Server {
final static ThreadLocal<Principal> PRINCIPAL = new ThreadLocal<>();
void serve(Request request, Response response) {
var level = (request.isAuthorized() ? ADMIN : GUEST);
var principal = new Principal(level);
PRINCIPAL.set(principal);
Application.handle(request, response);
}
}
class DBAccess {
DBConnection open() {
var principal = Server.PRINCIPAL.get();
if (!principal.canOpen()) throw new InvalidPrincipalException();
return newConnection(...);
}
}
这是我们常见的写法,但是使用 ThreadLocal 的问题是:
PRINCIPAL.set(principal)可以被任意设置修改。- 使用
ThreadLocal可能会忘记remove。 - 如果想要子线程继承共享的变量,需要占用新的内存空间。
- 在虚拟线程场景下,可能会有几十万线程,使用
ThreadLocal过于复杂,且有安全性能隐患。
虚拟线程自 Java 19 引入:JEP 425: 虚拟线程 (预览)
使用 ScopedValue
import jdk.incubator.concurrent.ScopedValue;
/**
* 启动命令加上 --add-modules jdk.incubator.concurrent
*
* @author https://www.wdbyte.com
*/
public class Jep429ScopedValueTest {
final static ScopedValue<String> SCOPED_VALUE = ScopedValue.newInstance();
public static void main(String[] args) {
// 创建线程
Thread thread1 = new Thread(Jep429ScopedValueTest::handle);
Thread thread2 = new Thread(Jep429ScopedValueTest::handle);
String str = "hello wdbyte";
// 传入线程里使用的字符串信息
ScopedValue.where(SCOPED_VALUE, str).run(thread1);
ScopedValue.where(SCOPED_VALUE, str).run(thread2);
// 执行完毕自动清空,这里获取不到了。
System.out.println(SCOPED_VALUE.orElse("没有信息"));
}
public static void handle() {
String result = SCOPED_VALUE.get();
System.out.println(result);
}
}
运行:
➜ src $ /jdk-20.0.1.jdk/Contents/Home/bin/java --version
openjdk 20.0.1 2023-04-18
OpenJDK Runtime Environment (build 20.0.1+9-29)
OpenJDK 64-Bit Server VM (build 20.0.1+9-29, mixed mode, sharing)
➜ src $ /jdk-20.0.1.jdk/Contents/Home/bin/java --add-modules jdk.incubator.concurrent Jep429ScopedValueTest.java
WARNING: Using incubator modules: jdk.incubator.concurrent
hello wdbyte.com
hello wdbyte.com
没有信息
可见使用 ScopedValue 有几个显而易见的好处。
- 代码方便,容易理解。符合编程逻辑。
- 不允许修改值,安全性高。(没有 set 方法)
- 生命周期明确。只传递到
run()方法体中。 - 不需要清理,自动释放。
- 从实现来讲,也是一种轻量级实现。
JEP 432: Record 模式匹配(二次预览)
在 Java 14 的 JEP 359 中增加了 Record 类,在 Java 16 的 JEP 394中,新增了 instanceof 模式匹配。
这两项都简化了 Java 开发的代码编写。在 Java 19 的 JEP 405 中,增又加了 Record 模式匹配功能的第一次预览,这把 JEP 359 和 JEP 394 的功能进行了结合,但是还不够强大,现在 JEP 432 又对其进行了增强。
JEP 359 功能回顾:
/**
* @author https://www.wdbyte.com
*/
public class RecordTest {
public static void main(String[] args) {
Dog dog = new Dog("name", 1);
System.out.println(dog.name()); // name
System.out.println(dog.age()); // 1
}
}
record Dog(String name, Integer age) {
}
JEP 394 功能回顾:
// Old code
if (obj instanceof String) {
String s = (String)obj;
... use s ...
}
// New code
if (obj instanceof String s) {
... use s ...
}
JEP 432 例子
而现在,可以进行更加复杂的组合嵌套,依旧可以准确识别类型。
/**
* @author https://www.wdbyte.com
*/
public class Jep432RecordAndInstance {
public static void main(String[] args) {
ColoredPoint coloredPoint1 = new ColoredPoint(new Point(0, 0), Color.RED);
ColoredPoint coloredPoint2 = new ColoredPoint(new Point(1, 1), Color.GREEN);
Rectangle rectangle = new Rectangle(coloredPoint1, coloredPoint2);
printUpperLeftColoredPoint(rectangle);
}
static void printUpperLeftColoredPoint(Rectangle r) {
if (r instanceof Rectangle(ColoredPoint ul, ColoredPoint lr)) {
System.out.println(ul.c());
}
}
}
record Point(int x, int y) {}
enum Color { RED, GREEN, BLUE }
record ColoredPoint(Point p, Color c) {}
record Rectangle(ColoredPoint upperLeft, ColoredPoint lowerRight) {}
输出:RED。
JEP 433: switch 模式匹配(四次预览)
Switch 的使用体验改造早在 Java 17 就已经开始了,下面是之前文章的一些介绍。
现在 JEP 433 进行第四次预览,对其功能进行了增强,直接从下面的新老代码看其变化。
/**
* @author https://www.wdbyte.com
*/
public class JEP433SwitchTest {
public static void main(String[] args) {
Object obj = 123;
System.out.println(matchOld(obj)); // 是个数字
System.out.println(matchNew(obj)); // 是个数字
obj = "wdbyte.com";
System.out.println(matchOld(obj)); // 是个字符串,长度大于2
System.out.println(matchNew(obj)); // 是个字符串,长度大于2
}
/**
* 老代码
*
* @param obj
* @return
*/
public static String matchOld(Object obj) {
if (obj == null) {
return "数据为空";
}
if (obj instanceof String) {
String s = obj.toString();
if (s.length() > 2) {
return "是个字符串,长度大于2";
}
if (s.length() <= 2) {
return "是个字符串,长度小于等于2";
}
}
if (obj instanceof Integer) {
return "是个数字";
}
throw new IllegalStateException("未知数据:" + obj);
}
/**
* 新代码
*
* @param obj
* @return
*/
public static String matchNew(Object obj) {
String res = switch (obj) {
case null -> "数据为空";
case String s when s.length() > 2 -> "是个字符串,长度大于2";
case String s when s.length() <= 2 -> "是个字符串,长度小于等于于2";
case Integer i -> "是个数字";
default -> throw new IllegalStateException("未知数据:" + obj);
};
return res;
}
}
JEP 434: 外部函数和内存 API(二次预览)
此功能引入的 API 允许 Java 开发者与 JVM 之外的代码和数据进行交互,通过调用外部函数(JVM 之外)和安全的访问外部内存(非 JVM 管理),让 Java 程序可以调用本机库并处理本机数据,而不会像 JNI 一样存在很多安全风险。
这不是一个新功能,自 Java 14 就已经引入,此次对其进行了性能、通用性、安全性、易用性上的优化。
历史
- Java 14 JEP 370 引入了外部内存访问 API(孵化器)。
- Java 15 JEP 383 引入了外部内存访问 API(第二孵化器)。
- Java 16 JEP 389 引入了外部链接器 API(孵化器)。
- Java 16 JEP 393 引入了外部内存访问 API(第三孵化器)。
- Java 17 JEP 412 引入了外部函数和内存 API(孵化器)。
- Java 18 JEP 419 引入了外部函数和内存 API(二次孵化器)。
- Java 19 JEP 424 引入了外部函数和内存 API(孵化器)。
JEP 436: 虚拟线程(二次预览)
通过将轻量级虚拟线程引入 Java 平台,简化了编写、维护和观察高吞吐量、并发应用程序的过程。使开发人员能够使用现有的 JDK 工具和技术轻松地排除故障、调试和分析并发应用程序,虚拟线程有助于加速应用程序开发。
这个特性自 Java 19 的 JEP 425: 虚拟线程 (预览)引入,在 Java 19 已经进行了详细介绍。
JEP 437: Structured Concurrency(二次孵化)
通过引入用于结构化并发 API 来简化多线程编程。结构化并发将在不同线程中运行的多个任务视为单个工作单元,从而简化错误处理,提高可靠性,增强可观察性。因为是个孵化状态提案,这里不做过多研究。
- 相关 Java 19,JEP 428:结构化并发(孵化)
JEP 438: Vector API(五次孵化)
再次提高性能,实现优于等效标量计算的性能。这是通过引入一个 API 来表达矢量计算,该 API 在运行时可靠地编译为支持的 CPU 架构上的最佳矢量指令,从而实现优于等效标量计算的性能。Vector API 在 JDK 16 到 19 中孵化。JDK 20 整合了这些版本用户的反馈以及性能改进和实现增强。
一如既往,文章中代码存放在 Github.com/niumoo/javaNotes.
文章持续更新,可以微信搜一搜「 程序猿阿朗 」或访问「程序猿阿朗博客 」第一时间阅读。本文 Github.com/niumoo/JavaNotes 已经收录,有很多系列文章,欢迎Star。
Java 20 新功能介绍的更多相关文章
- Java 19 新功能介绍
点赞再看,动力无限. 微信搜「程序猿阿朗 」. 本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章. Java 19 在2022 年 9 ...
- Java 14 新功能介绍
不做标题党,认认真真写个文章. 文章已经收录在 Github.com/niumoo/JavaNotes 和未读代码博客,点关注,不迷路. Java 14 早在 2019 年 9 月就已经发布,虽然不是 ...
- 超详细 Java 15 新功能介绍
点赞再看,动力无限.微信搜「程序猿阿朗 」,认认真真写文章. 本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章. Java 15 在 2 ...
- Java 17 新功能介绍(LTS)
点赞再看,动力无限.Hello world : ) 微信搜「程序猿阿朗 」. 本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章. Jav ...
- Java 16 新功能介绍
点赞再看,动力无限.Hello world : ) 微信搜「程序猿阿朗 」. 本文 Github.com/niumoo/JavaNotes 和 程序猿阿朗博客 已经收录,有很多知识点和系列文章. Ja ...
- Java 18 新功能介绍
文章持续更新,可以关注公众号程序猿阿朗或访问未读代码博客. 本文 Github.com/niumoo/JavaNotes 已经收录,欢迎Star. Java 18 在2022 年 3 月 22 日正式 ...
- CentOS以及Oracle数据库发展历史及各版本新功能介绍, 便于构造环境时有个对应关系
CentOS版本历史 版本 CentOS版本号有两个部分,一个主要版本和一个次要版本,主要和次要版本号分别对应于RHEL的主要版本与更新包,CentOS采取从RHEL的源代码包来构建.例如CentOS ...
- Java 11 新特性介绍
Java 11 已于 2018 年 9 月 25 日正式发布,之前在Java 10 新特性介绍中介绍过,为了加快的版本迭代.跟进社区反馈,Java 的版本发布周期调整为每六个月一次——即每半年发布一个 ...
- Java 12 新特性介绍,快来补一补
Java 12 早在 2019 年 3 月 19 日发布,它不是一个长久支持(LTS)版本.在这之前我们已经介绍过其他版本的新特性,如果需要可以点击下面的链接进行阅读. Java 11 新特性介绍 J ...
- 原创开源项目HierarchyViewer for iOS 2.1 Beta新功能介绍
回顾 HierarchyViewer for iOS是我们发布的一个开源项目,采用GPL v3.0协议. HierarchyViewer for iOS可以帮助iOS应用的开发和测试人员,在没有源代码 ...
随机推荐
- 关于UPD章节学习的一些感想
课程看到了UDP, 首先了解UDP的原理模型. 服务端,首先是实例QUdpSocket,也就是UDP套接字,然后,需要绑定.绑定一个任意IP地址,分为IPV4和IPV6.自行选择课程中讲解时绑定的是I ...
- Markdown操作方法
Markdown学习 标题 三级标题 四级标题 字体 原本 hello,world! 斜体 hello,world! 加粗 hello,world! 斜体加粗 hello,world! 删除 hell ...
- 关于 Android sdk manager 的安装问题
最近刚刚接触小程序测试,故此需要搭建环境 我用的是python3.6+appium1.8.2+Android sdk manager 关于应用程序,大家有需要的话,可以找我要. 1.关于安装Andro ...
- 如何搭建属于自己的服务器(Linux7.6版)
从0搭建属于自己的服务器 最近小伙伴推荐的华为云活动,购买服务器相当的划算,本人也是耗费巨资购买了一台2核4G HECS云服务器. 话不多说,在这里给华为云打一个广子,活动力度还是很不错的. 活动详情 ...
- 【数据结构与算法学习】散列表(Hash Table,哈希表)
实现语言:C++ 1. 散列表 散列表,英文名称为Hash Table,又称哈希表.杂凑表等. 线性表和树表的查找是通过比较关键字的方法,查找的效率取决于关键字的比较次数. 而散列表是根据关键字直接访 ...
- 百度生成式AI产品文心一言邀你体验AI创作新奇迹:百度CEO李彦宏详细透露三大产业将会带来机遇(文末附文心一言个人用户体验测试邀请码获取方法,亲测有效)
目录 中国版ChatGPT上线发布 强大中文理解能力 智能文学创作.商业文案创作 图片.视频智能生成 中国生成式AI三大产业机会 新型云计算公司 行业模型精调公司 应用服务提供商 总结 获取文心一言邀 ...
- SICP:求值和环境模型(Python实现)
绪论 我们在第一章引进复合过程时,采用了求值的代换模型定义了将过程应用于实参(arguments)的意义: 将一个复合过程应用于一些实参,也就意味着用实参替换过程体里对应的形参(formal para ...
- 【LeetCode动态规划#02】图解不同路径I + II(首次涉及二维dp数组,)
不同路径 力扣题目链接(opens new window) 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 "Start" ). 机器人每次只能向下或者向右移 ...
- 网络图片的爬取和存储.py(亲测有效)
import requests import os url = "https://ss0.baidu.com/7Po3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/i ...
- 机器学习基础07DAY
分类算法之决策树 决策树是一种基本的分类方法,当然也可以用于回归.我们一般只讨论用于分类的决策树.决策树模型呈树形结构.在分类问题中,表示基于特征对实例进行分类的过程,它可以认为是if-then规则的 ...