新聞中心
?Java 19 在2022 年 9 月 20 日正式發(fā)布,Java 19 不是一個長期支持版本,直到 2023 年 3 月它將被 JDK 20 取代,這次更新共帶來 7 個新功能。

bin ./java -version
openjdk version "19" 2022-09-20
OpenJDK Runtime Environment (build 19+36-2238)
OpenJDK 64-Bit Server VM (build 19+36-2238, mixed mode, sharing)
OpenJDK Java 19 下載:https://jdk.java.net/19/
OpenJDK Java 19 文檔:https://openjdk.java.net/projects/jdk/19/
Java 19 帶來的 7 個新特性:
|
JEP |
描述 |
|
405 |
Record 模式匹配 (Preview) |
|
425 |
虛擬線程 (預(yù)覽) |
|
427 |
Switch 模式匹配 (三次預(yù)覽) |
|
422 |
Linux/RISC-V Port |
|
426 |
Vector API (四次孵化) |
|
424 |
外部函數(shù) & 內(nèi)存 API (Preview) |
|
428 |
Structured Concurrency (Incubator) |
Java 19 新功能介紹是 Java 新特性系列文章中的一部分。系列詳情可以瀏覽:https://www.wdbyte.com/java-feature/
JEP 405: Record 模式匹配(預(yù)覽)
record? 是一種全新的類型,它本質(zhì)上是一個 final? 類,同時所有的屬性都是 final? 修飾,它會自動編譯出 public get hashcode? 、equals、toString 等方法,減少了代碼編寫量。Record 在 Java 14 中被提出,在 Java 15 中二次預(yù)覽,在 Java 16 中正式發(fā)布。
示例:編寫一個 Dog record 類,定義 name 和 age 屬性。
package com.wdbyte;
public record Dog(String name, Integer age) {
}
Record 的使用。
package com.wdbyte;
public class Java14Record {
public static void main(String[] args) {
Dog dog1 = new Dog("牧羊犬", 1);
Dog dog2 = new Dog("田園犬", 2);
Dog dog3 = new Dog("哈士奇", 3);
System.out.println(dog1);
System.out.println(dog2);
System.out.println(dog3);
}
}
輸出結(jié)果:
Dog[name=牧羊犬, age=1]
Dog[name=田園犬, age=2]
Dog[name=哈士奇, age=3]
在 Java 19 中,為 Record 帶來了增強(qiáng)的模式匹配,在使用 instanceof 后,可以進(jìn)行類型轉(zhuǎn)換。
public class RecordTest {
public static void main(String[] args) {
Object dog1 = new Dog("牧羊犬", 1);
if(dog1 instanceof Dog dogTemp){
System.out.println(dogTemp.name());
}
}
}
record Dog( String name, Integer age ){
}甚至可以在使用 instanceof? 時直接得到 Record 中的變量引用。
public class RecordTest2 {
public static void main(String[] args) {
Object dog1 = new Dog("牧羊犬", 1);
if(dog1 instanceof Dog(String name,Integer age)){
System.out.println(name+":"+age);
}
}
}
record Dog( String name, Integer age ){
}擴(kuò)展:
Java 14 instanceof 類型推斷
Java 16 Record 介紹
JEP 425: 虛擬線程 (預(yù)覽)
很實(shí)用的一個新特性,從 Java 19 開始逐步的引入虛擬線程,虛擬線程是輕量級的線程,可以在顯著的減少代碼的編寫,提高可維護(hù)性的同時提高系統(tǒng)的吞吐量。
引入的原因
一直以來,在 Java 并發(fā)編程中,Thread 都是十分重要的一部分,Thread 是 Java 中的并發(fā)單元,每個 Thread 線程都提供了一個堆棧來存儲局部變量和方法調(diào)用,以及線程上下文等相關(guān)信息。
但問題是線程和進(jìn)程一樣,都是一項(xiàng)昂貴的資源,JDK 將 Thread 線程實(shí)現(xiàn)為操作系統(tǒng)線程的包裝器,也就是說成本很高,而且數(shù)量有限。也因此我們會使用線程池來管理線程,同時限制線程的數(shù)量。比如常用的 Tomcat 會為每次請求單獨(dú)使用一個線程進(jìn)行請求處理,同時限制處理請求的線程數(shù)量以防止線程過多而崩潰;這很有可能在 CPU 或網(wǎng)絡(luò)連接沒有耗盡之前,線程數(shù)量已經(jīng)耗盡,從而限制了 web 服務(wù)的吞吐量。
看到這里你可能要說了,可以放棄請求和線程一一對應(yīng)的方式啊,使用異步編程來解決這個問題,把請求處理分段,在組合成順序管道,通過一套 API 進(jìn)行管理,這樣就可以使用有限的線程來處理超過線程數(shù)量的請求。這當(dāng)然也是可以的,但是隨之而來的問題是:
- 需要額外的學(xué)習(xí)異步編程。
- 代碼復(fù)雜度增加,等于放棄了語言的基本順序組合運(yùn)算。
- 堆棧上下文信息都變得難以追蹤。
- Debug 困難。
- 和 Java 平臺本身的編程風(fēng)格有沖突,Java 并發(fā)單元是 Thread,而這時是異步管道。
虛擬線程
基于上面的種種原因,Java 19 引入了虛擬線程,在使用體驗(yàn)上和 Thread 沒有區(qū)別,與之前的 API 互相兼容,但是相比之下虛擬線程資源占用非常少,同時優(yōu)化了硬件的使用效率,因此非常易用且不需要被池化。
下面是一個示例,創(chuàng)建 10 萬個線程,然后都休眠 1 秒鐘最后打印耗時,如果是開傳統(tǒng)的 Thread 線程的方式,資源十分緊張;如果是線程池的方式,必定有部分線程在等待線程釋放;但是使用虛擬線程的方式,可以瞬間完成。
import java.util.concurrent.Executors;
import java.util.stream.IntStream;
public class ThreadTest {
public static void main(String[] args) {
long start = System.currentTimeMillis();
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 100_000).forEach(i -> {
executor.submit(() -> {
Thread.sleep(1000);
return i;
});
});
}
System.out.println("耗時:" + (System.currentTimeMillis() - start)+"ms");
}
}
執(zhí)行后發(fā)現(xiàn) 1.3 秒執(zhí)行完畢,速度驚人。
bin ./java --enable-preview --source 19 ThreadTest.java
注: ThreadTest.java 使用 Java SE 19 的預(yù)覽功能。
注: 有關(guān)詳細(xì)信息,請使用 -Xlint:preview 重新編譯。
耗時:1309ms
bin
注意:虛擬線程只是增加程序的吞吐量,并不能提高程序的處理速度。
JEP 427: switch 模式匹配 (三次預(yù)覽)
Switch 模式匹配在 Java 17 中已經(jīng)引入,在 Java 18 中二次預(yù)覽,現(xiàn)在在 Java 19 中進(jìn)行三次預(yù)覽,功能和在 Java 18 新功能介紹 - Switch 中介紹的一樣,改進(jìn)后的 Switch 模式匹配可以代碼更加簡潔,邏輯更加清晰,下面是一些使用示例對比。
下面是幾個例子:
static String formatter(Object o) {
String formatted = "unknown";
if (o instanceof Integer i) {
formatted = String.format("int %d", i);
} else if (o instanceof Long l) {
formatted = String.format("long %d", l);
} else if (o instanceof Double d) {
formatted = String.format("double %f", d);
} else if (o instanceof String s) {
formatted = String.format("String %s", s);
}
return formatted;
}而在 Java 17 之后,可以通過下面的寫法進(jìn)行改進(jìn):
static String formatterPatternSwitch(Object o) {
return switch (o) {
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);
default -> o.toString();
};
}switch 可以和 null 進(jìn)行結(jié)合判斷:
static void testFooBar(String s) {
switch (s) {
case null -> System.out.println("Oops");
case "Foo", "Bar" -> System.out.println("Great");
default -> System.out.println("Ok");
}
}case 時可以加入復(fù)雜表達(dá)式:
static void testTriangle(Shape s) {
switch (s) {
case Triangle t && (t.calculateArea() > 100) ->
System.out.println("Large triangle");
default ->
System.out.println("A shape, possibly a small triangle");
}
}case 時可以進(jìn)行類型判斷:
sealed interface S permits A, B, C {}
final class A implements S {}
final class B implements S {}
record C(int i) implements S {} // Implicitly final
static int testSealedExhaustive(S s) {
return switch (s) {
case A a -> 1;
case B b -> 2;
case C c -> 3;
};
}擴(kuò)展:JEP 406:Switch 的類型匹配(預(yù)覽)
JEP 422: Linux/RISC-V Port
RISC-V是一個免費(fèi)和開源的 RISC 指令集架構(gòu) (ISA),實(shí)際上 RISC-V 是一系列相關(guān)的 ISA,現(xiàn)在 Java 19 開始對其進(jìn)行支持。
JEP 424: 外部函數(shù) & 內(nèi)存 API (預(yù)覽)
此功能引入的 API 允許 Java 開發(fā)者與 JVM 之外的代碼和數(shù)據(jù)進(jìn)行交互,通過調(diào)用外部函數(shù)(JVM之外)和安全的訪問外部內(nèi)存(非 JVM 管理),讓 Java 程序可以調(diào)用本機(jī)庫并處理本機(jī)數(shù)據(jù),而不會像 JNI 一樣存在很多安全風(fēng)險。
這不是一個新功能,自 Java 14 就已經(jīng)引入,此次對其進(jìn)行了性能、通用性、安全性、易用性上的優(yōu)化。
歷史
- Java 14JEP 370 引入了外部內(nèi)存訪問 API(孵化器)。
- Java 15JEP 383引入了外部內(nèi)存訪問 API(第二孵化器)。
- Java 16JEP 389引入了外部鏈接器 API(孵化器)。
- Java 16JEP 393引入了外部內(nèi)存訪問 API(第三孵化器)。
- Java 17JEP 412引入了外部函數(shù)和內(nèi)存 API(孵化器)。
- Java 18JEP 419引入了外部函數(shù)和內(nèi)存 API(二次孵化器)。
其他更新
JEP 426: Vector API (四次孵化)
通過將在運(yùn)行時可靠地編譯為支持的 CPU 架構(gòu)上的向量指令的向量計算表示,與等效的標(biāo)量計算相比,實(shí)現(xiàn)了卓越的性能。此功能已經(jīng)第四次孵化,在之前 Java 16 ~ Java 18 中都有介紹,這里不做贅述。
JEP 428: Structured Concurrency (孵化)
通過簡化多線程編程并將在不同線程中運(yùn)行的多個任務(wù)視為單個工作單元,簡化錯誤處理和取消,提高可靠性并增強(qiáng)可觀察性。
本文題目:聊聊 Java 19 新功能,你學(xué)會了嗎?
URL鏈接:http://fisionsoft.com.cn/article/dpedshd.html


咨詢
建站咨詢
