Java 19 在数分钟前正式发布,这是一个非 LTS(长期支持)版本,该版本的七项功能包括结构化并发、记录模式、外部函数和内存 API 的预览,以及对开源 Linux/RISC-V
指令集架构 (ISA) 的支持。
这是对Java 17正式生效的Record Class的增强。JEP 405让记录模式和类型模式可以嵌套,以实现强大的、可声明的、可组合的数据处理形式。
在JDK 16 中,我们已经可以实现下列特性:
// jdk 16 以前
if (o instanceof String) {
// 及时类型匹配 依然需要转换
String s = (String)o;
}
// jdk 16 以后
if (o instanceof String s) {
// 直接使用 s
}
但是上面的特性应用在Record Class中并不是很丝滑,依然需要通过属性方法来获取属性值:
public record Position(int x, int y) {}
// record 结合类型匹配 依然需要通过方法获取属性
private void print(Object object) {
if (object instanceof Position position) {
int x = position.x();
int y = position.y();
}
}
JEP 405中我们可以这样:
private void print(Object object) {
if (object instanceof Position(int x, int y)) {
// 直接使用 x 和 y
}
}
当然这仅仅是 JEP 405 的一小部分,该特性也可以应用到switch
语句,甚至是嵌套条件中。
由于 RISC-V 指令集架构的硬件越来越多,从Java 19开始提供相应架构的端口。
RISC-V是一个免费和开源的 RISC 指令集架构 (ISA),最初由加州大学伯克利分校设计,现在在RISC-V International的赞助下合作开发。它已经被广泛的语言工具链支持。随着 RISC-V 硬件的日益普及,JDK 的移植将是有价值的。
通过该特性,Java 程序可以通过 API 与 Java 运行时之外的代码和数据进行互操作。通过有效地调用外部函数(即JVM之外的代码)和安全地访问外部内存(即不受 JVM 管理的内存),API 使 Java 程序能够调用 native 库并处理 native 数据,比使用JNI更加安全。这个JEP并不是第一次预览,从JDK 14开始陆续相关的特性都经过孵化和预览,本次是对以往的相关预览特性的改进。
虚拟线程,关于虚拟线程之前胖哥有文章进行来专门讲解科普,有兴趣可以通过这篇文章进行了解。
传统线程和虚拟线程
在本次 Java 19 中虚拟线程正式以预览的状态亮相,这能够简化对多线程的操作,让以往“昂贵”的线程更加“廉价”。
引入一个 API 来表达向量计算,该计算可以在运行时可靠地编译为支持的 CPU 架构上的最佳向量指令,从而实现优于等效标量计算的性能。这个特性已经算老面孔了,已经是第四次预览了。
switch
语句的匹配模式,目前还没有转正,这是它第三次预览。胖哥已经多次介绍该特性,可以去胖哥往期JDK发布的文章看看。
结构化并发,听起来很厉害的样子。通过引入用于结构化并发的 API 来简化多线程编程。结构化并发将在不同线程中运行的多个任务视为单个工作单元,从而简化错误处理和取消,提高可靠性并增强可观察性。这是一个孵化 API 。
结构化并发 API 的主体类是StructuredTaskScope
。此类允许开发人员将任务构建为一系列并发子任务,并将它们作为一个单元进行协调。子任务在它们自己的线程中执行,方法是将它们单独分叉(fork),然后将它们作为一个单元加入,并可能将它们作为一个单元取消( cancel )。子任务的成功结果或异常由父任务聚合和处理。StructuredTaskScope
将子任务或分叉的生命周期限制在明确的词法范围内,这样我们可以像写单线程代码一样来写多线程代码。官方给来一个例子:
Response handle() throws ExecutionException, InterruptedException {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
Future<String> user = scope.fork(() -> findUser());
Future<Integer> order = scope.fork(() -> fetchOrder());
scope.join(); // Join both forks
scope.throwIfFailed(); // ... and propagate errors
// Here, both forks have succeeded, so compose their results
return new Response(user.resultNow(), order.resultNow());
}
}
❝Java 的多线程对开发者历来都是“魔鬼”,这个特性有望改善这一状况。