共计 5460 个字符,预计需要花费 14 分钟才能阅读完成。
点赞 再看,能源有限。微信搜「程序猿阿朗」。
本文 Github.com/niumoo/JavaNotes 和 未读代码博客 曾经收录,有很多知识点和系列文章。
Java 19 在 2022 年 9 月 20 日正式公布,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 | 虚构线程 (预览) |
427 | Switch 模式匹配 (三次预览) |
422 | Linux/RISC-V Port |
426 | Vector API (四次孵化) |
424 | 内部函数 & 内存 API (Preview) |
428 | Structured Concurrency (Incubator) |
Java 19 新性能介绍是 Java 新个性系列文章中的一部分。
系列详情能够浏览:https://www.wdbyte.com/java-feature/
JEP 405: Record 模式匹配(预览)
record
是一种全新的类型,它实质上是一个 final
类,同时所有的属性都是 final
润饰,它会主动编译出 public get
hashcode
、equals
、toString
等办法,缩小了代码编写量。Record 在 Java 14 中被提出,在 Java 15 中二次预览,在 Java 16 中正式公布。
示例:编写一个 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);
}
}
输入后果:
Dog[name= 牧羊犬, age=1]
Dog[name= 田园犬, age=2]
Dog[name= 哈士奇, age=3]
在 Java 19 中,为 Record 带来了加强的模式匹配,在应用 instanceof
后,能够进行类型转换。
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){
}
// ➜ bin ./java RecordTest.java
// 牧羊犬
甚至能够在应用 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){
}
//➜ bin ./java --enable-preview --source 19 RecordTest2.java
// 注: RecordTest2.java 应用 Java SE 19 的预览性能。// 注: 无关详细信息,请应用 -Xlint:preview 从新编译。// 牧羊犬:1
扩大:
Java 14 instanceof 类型推断
Java 16 Record 介绍
JEP 425: 虚构线程 (预览)
很实用 的一个新个性,从 Java 19 开始逐渐的引入虚构线程,虚构线程是 轻量级的线程 ,能够在显著的缩小代码的编写,进步可维护性的同时进步零碎的 吞吐量。
引入的起因
始终以来,在 Java 并发编程中,Thread 都是非常重要的一部分,Thread 是 Java 中的并发单元,每个 Thread 线程都提供了一个堆栈来存储局部变量和办法调用,以及线程上下文等相干信息。
但问题是线程和过程一样,都是一项 低廉的资源 ,JDK 将 Thread 线程实现为操作系统线程的包装器,也就是说老本很高,而且数量无限。也因而咱们会应用线程池来治理线程,同时限度线程的数量。比方罕用的 Tomcat 会 为每次申请独自应用一个线程进行申请解决 ,同时限度解决申请的线程数量以避免线程过多而解体;这很有可能 在 CPU 或网络连接没有耗尽之前,线程数量曾经耗尽,从而限度了 web 服务的吞吐量。
看到这里你可能要说了,能够放弃申请和线程一一对应的形式啊,应用异步编程来解决这个问题,把申请解决分段,在组合成程序管道,通过一套 API 进行治理,这样就能够应用无限的线程来解决超过线程数量的申请。这当然也是能够的,然而随之而来的问题是:
- 须要额定的学习异步编程。
- 代码复杂度减少,等于放弃了语言的根本程序组合运算。
- 堆栈上下文信息都变得难以追踪。
- Debug 艰难。
- 和 Java 平台自身的编程格调有抵触,Java 并发单元是 Thread,而这时是异步管道。
虚构线程
基于下面的种种原因,Java 19 引入了虚构线程,在应用体验上和 Thread 没有区别,与之前的 API 相互兼容,然而相比之下虚构线程资源占用非常少,同时优化了硬件的应用效率,因而十分易用且 不须要被池化。
上面是一个示例,创立 10 万个线程,而后都休眠 1 秒钟最初打印耗时,如果是开传统的 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;
});
});
} // executor.close() 会被主动调用
// 提交了 10 万个虚构线程,每个线程休眠 1 秒钟,1 秒左右实现
System.out.println("耗时:" + (System.currentTimeMillis() - start)+"ms");
}
}
执行后发现 1.3 秒执行结束,速度惊人。
➜ bin ./java --enable-preview --source 19 ThreadTest.java
注: ThreadTest.java 应用 Java SE 19 的预览性能。注: 无关详细信息,请应用 -Xlint:preview 从新编译。耗时:1309ms
➜ bin
留神:虚构线程只是减少程序的吞吐量,并不能进步程序的处理速度。
JEP 427: switch 模式匹配 (三次预览)
Switch 模式匹配在 Java 17 中曾经引入,在 Java 18 中二次预览,当初在 Java 19 中进行三次预览,性能和在 Java 18 新性能介绍 – Switch 中介绍的一样,改良后的 Switch 模式匹配能够代码更加简洁,逻辑更加清晰,上面是一些应用示例比照。
上面是几个例子:
// JDK 17 以前
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 之后,能够通过上面的写法进行改良:
// JDK 17 之后
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
进行联合判断:
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 时能够退出简单表达式:
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 时能够进行类型判断:
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;
};
}
扩大:JEP 406:Switch 的类型匹配(预览)
JEP 422: Linux/RISC-V Port
RISC- V 是一个收费和开源的 RISC 指令集架构 (ISA),实际上 RISC-V 是一系列相干的 ISA,当初 Java 19 开始对其进行反对。
JEP 424: 内部函数 & 内存 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(二次孵化器)。
其余更新
JEP 426: Vector API (四次孵化)
通过将在运行时牢靠地编译为反对的 CPU 架构上的向量指令的向量计算示意,与等效的标量计算相比,实现了卓越的性能。此性能曾经第四次孵化,在之前 Java 16 ~ Java 18 中都有介绍,这里不做赘述。
JEP 428: Structured Concurrency (孵化)
通过简化多线程编程并将在不同线程中运行的多个工作视为单个工作单元,简化错误处理和勾销,进步可靠性并加强可察看性。
判若两人,文章中代码寄存在 Github.com/niumoo/javaNotes.
< 完 >
文章继续更新,能够微信搜一搜「程序猿阿朗 」或拜访「 程序猿阿朗博客」第一工夫浏览。本文 Github.com/niumoo/JavaNotes 曾经收录,有很多知识点和系列文章,欢送 Star。