Java 19 正式发布,改善多线程、并发编程难度

2022-10-05 18:43:28 浏览数 (1)

Java 19 在数分钟前正式发布,这是一个非 LTS(长期支持)版本,该版本的七项功能包括结构化并发、记录模式、外部函数和内存 API 的预览,以及对开源 Linux/RISC-V 指令集架构 (ISA) 的支持。

新特性

  • JEP 405 Record Patterns (预览)
  • JEP 422 Linux/RISC-V Port
  • JEP 424 Foreign Function & Memory API (预览)
  • JEP 425 Virtual Threads (预览)
  • JEP 426 Vector API (第四次孵化)
  • JEP 427 Pattern Matching for switch (第三次预览)
  • JEP 428 Structured Concurrency (孵化)

JEP 405 Record Patterns

这是对Java 17正式生效的Record Class的增强。JEP 405让记录模式和类型模式可以嵌套,以实现强大的、可声明的、可组合的数据处理形式。

在JDK 16 中,我们已经可以实现下列特性:

代码语言:javascript复制
// jdk 16 以前
if (o instanceof String) {
    // 及时类型匹配 依然需要转换
    String s = (String)o;     
}

// jdk 16 以后
if (o instanceof String s) {
    // 直接使用 s 
}

但是上面的特性应用在Record Class中并不是很丝滑,依然需要通过属性方法来获取属性值:

代码语言:javascript复制
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中我们可以这样:

代码语言:javascript复制
private void print(Object object) {
  if (object instanceof Position(int x, int y)) {
      // 直接使用 x 和 y
  } 
}

当然这仅仅是 JEP 405 的一小部分,该特性也可以应用到switch语句,甚至是嵌套条件中。

JEP 422 Linux/RISC-V Port

由于 RISC-V 指令集架构的硬件越来越多,从Java 19开始提供相应架构的端口。

RISC-V是一个免费和开源的 RISC 指令集架构 (ISA),最初由加州大学伯克利分校设计,现在在RISC-V International的赞助下合作开发。它已经被广泛的语言工具链支持。随着 RISC-V 硬件的日益普及,JDK 的移植将是有价值的。

JEP 424 Foreign Function & Memory API

通过该特性,Java 程序可以通过 API 与 Java 运行时之外的代码和数据进行互操作。通过有效地调用外部函数(即JVM之外的代码)和安全地访问外部内存(即不受 JVM 管理的内存),API 使 Java 程序能够调用 native 库并处理 native 数据,比使用JNI更加安全。这个JEP并不是第一次预览,从JDK 14开始陆续相关的特性都经过孵化和预览,本次是对以往的相关预览特性的改进。

JEP 425 Virtual Threads

虚拟线程,关于虚拟线程之前胖哥有文章进行来专门讲解科普,有兴趣可以通过这篇文章进行了解。

传统线程和虚拟线程

在本次 Java 19 中虚拟线程正式以预览的状态亮相,这能够简化对多线程的操作,让以往“昂贵”的线程更加“廉价”。

JEP 426 Vector API

引入一个 API 来表达向量计算,该计算可以在运行时可靠地编译为支持的 CPU 架构上的最佳向量指令,从而实现优于等效标量计算的性能。这个特性已经算老面孔了,已经是第四次预览了。

JEP 427 Pattern Matching for switch

switch语句的匹配模式,目前还没有转正,这是它第三次预览。胖哥已经多次介绍该特性,可以去胖哥往期JDK发布的文章看看。

JEP 428 Structured Concurrency

结构化并发,听起来很厉害的样子。通过引入用于结构化并发的 API 来简化多线程编程。结构化并发将在不同线程中运行的多个任务视为单个工作单元,从而简化错误处理和取消,提高可靠性并增强可观察性。这是一个孵化 API 。

结构化并发 API 的主体类是StructuredTaskScope。此类允许开发人员将任务构建为一系列并发子任务,并将它们作为一个单元进行协调。子任务在它们自己的线程中执行,方法是将它们单独分叉(fork),然后将它们作为一个单元加入,并可能将它们作为一个单元取消( cancel )。子任务的成功结果或异常由父任务聚合和处理。StructuredTaskScope将子任务或分叉的生命周期限制在明确的词法范围内,这样我们可以像写单线程代码一样来写多线程代码。官方给来一个例子:

代码语言:javascript复制
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 的多线程对开发者历来都是“魔鬼”,这个特性有望改善这一状况。

0 人点赞