行业知识
JDK21 新特性
2026-10-26 02:24:17
来源:互联网转载
目录
- 1. 虚拟线程(Virtual Threads)
- 2. 有序集合(Sequenced Collections)
- 3. switch 的模式匹配(Pattern Matching for switch)
- 4. 记录模式(Record Patterns)
- 5. ZGC
- 6. 准备禁用动态代理(Prepare to Disallow the Dynamic Loading of Agents)
1. 虚拟线程(Virtual Threads)
https://openjdk.org/jeps/444
- 虚拟线程是工作在平台线程之上的,虚拟线程的数量可以远大于操作系统线程的数量,多个虚拟线程挂载在一个平台线程上,一个平台线程可以在不同的时间执行不同的虚拟线程,当虚拟线程被阻塞或等待时,平台线程可以切换到执行另一个虚拟线程。
注意事项:
- 虚拟线程主要作用是提升服务器端的吞吐量,而不是提高线程的执行速度。
- 虚拟线程只适合IO密集型的任务,阻塞期间可以将CPU资源让渡给其他任务,不适合CPU密集型的任务或非阻塞任务。
- 虚拟线程是廉价且轻量级的,使用完后立即被销毁,因此不需要池化。
- 创建虚拟线程的方法
import lombok.extern.slf4j.Slf4j;import java.time.Duration;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ThreadFactory;import java.util.stream.IntStream;@Slf4jpublic class Demo { public static void main(String[] args) throws Exception { Runnable task = () -> { log.info(Thread.currentThread().toString()); }; // 1. 通过 Thread.ofVirtual() 创建 Thread thread = Thread.ofVirtual().name(Thread.currentThread().toString()).start(task); // 2. 通过 Thread.startVirtualThread() 创建 Thread.startVirtualThread(task); // 3. 通过 ThreadFactory 创建 ThreadFactory factory = Thread.ofVirtual().factory(); Thread newThread = factory.newThread(task); newThread.start(); // 4. 通过 Executors.newVirtualThreadPerTaskExecutor() 创建 try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) { IntStream.range(0, 5).forEach(i -> { executor.submit(() -> { log.info("{}, before", Thread.currentThread()); try { Thread.sleep(Duration.ofSeconds(1)); } catch (InterruptedException e) { throw new RuntimeException(e); } log.info("{}, after", Thread.currentThread()); }); }); } System.in.read(); }}- 打印
19:49:16.027 [] INFO org.example.virtual_thread.Demo -- VirtualThread[#22]/runnable@ForkJoinPool-1-worker-219:49:16.027 [Thread[#1,main,5,main]] INFO org.example.virtual_thread.Demo -- VirtualThread[#20,Thread[#1,main,5,main]]/runnable@ForkJoinPool-1-worker-119:49:16.029 [] INFO org.example.virtual_thread.Demo -- VirtualThread[#23]/runnable@ForkJoinPool-1-worker-219:49:16.029 [] INFO org.example.virtual_thread.Demo -- VirtualThread[#25]/runnable@ForkJoinPool-1-worker-1, before19:49:16.030 [] INFO org.example.virtual_thread.Demo -- VirtualThread[#27]/runnable@ForkJoinPool-1-worker-2, before19:49:16.029 [] INFO org.example.virtual_thread.Demo -- VirtualThread[#26]/runnable@ForkJoinPool-1-worker-2, before19:49:16.031 [] INFO org.example.virtual_thread.Demo -- VirtualThread[#28]/runnable@ForkJoinPool-1-worker-1, before19:49:16.031 [] INFO org.example.virtual_thread.Demo -- VirtualThread[#29]/runnable@ForkJoinPool-1-worker-1, before19:49:17.033 [] INFO org.example.virtual_thread.Demo -- VirtualThread[#27]/runnable@ForkJoinPool-1-worker-1, after19:49:17.033 [] INFO org.example.virtual_thread.Demo -- VirtualThread[#25]/runnable@ForkJoinPool-1-worker-2, after19:49:17.033 [] INFO org.example.virtual_thread.Demo -- VirtualThread[#28]/runnable@ForkJoinPool-1-worker-2, after19:49:17.033 [] INFO org.example.virtual_thread.Demo -- VirtualThread[#26]/runnable@ForkJoinPool-1-worker-1, after19:49:17.033 [] INFO org.example.virtual_thread.Demo -- VirtualThread[#29]/runnable@ForkJoinPool-1-worker-2, after
- 通过25号虚拟线程可以看出,阻塞前后使用的平台线程发生过切换
- VirtualThread[#22]/runnable@ForkJoinPool-1-worker-2表示VirtualThread[#22]这个虚拟线程依赖于平台线程ForkJoinPool-1-worker-2,这里我在VM参数中添加了-Djdk.virtualThreadScheduler.maxPoolSize=2 -Djdk.virtualThreadScheduler.parallelism=2,限制平台线程最大2个,所以只能会看到ForkJoinPool-1-worker-1和ForkJoinPool-1-worker-2两个平台线程。
- 虚拟线程在block后,会与平台线程解绑,然后加入任务列表排队,等待分配给平台线程
2. 有序集合(Sequenced Collections)
https://openjdk.org/jeps/431
- Sequenced Collections是一种具有确定出现顺序的集合。提供了处理集合第一个和最后一个元素以及反转集合的简单方法。
Sequenced Collections 包括以下三个接口:
- SequencedCollection
- SequencedSet
- SequencedMap
interface SequencedCollection extends Collection { // New Method SequencedCollection reversed(); // Promoted methods from Deque void addFirst(E); void addLast(E); E getFirst(); E getLast(); E removeFirst(); E removeLast();}3. switch 的模式匹配(Pattern Matching for switch)
https://openjdk.org/jeps/441
- 属于语法方面的升级,增强了 switch 表达式,允许在 case 标签中使用模式。
- JDK21之前
// Prior to Java 21static String formatter(Object obj) { String formatted = "unknown"; if (obj instanceof Integer i) { formatted = String.format("int %d", i); } else if (obj instanceof Long l) { formatted = String.format("long %d", l); } else if (obj instanceof Double d) { formatted = String.format("double %f", d); } else if (obj instanceof String s) { formatted = String.format("String %s", s); } return formatted;}- JDK21之后
// As of Java 21static String formatterPatternSwitch(Object obj) { return switch (obj) { 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 -> obj.toString(); };}4. 记录模式(Record Patterns)
https://openjdk.org/jeps/440
- 记录模式(Record Patterns) 可对 record 的值进行解构,也就是更方便地从记录类(Record Class)中提取数据。并且,记录模式和类型模式可以嵌套使用,以实现强大的、声明性的和可组合的数据导航和处理形式。
- 记录模式不能单独使用,而是要与 instanceof 或 switch 模式匹配一同使用。
- 以 instanceof 为例
// As of Java 16record Point(int x, int y) {}static void printSum(Object obj) { if (obj instanceof Point p) { int x = p.x(); int y = p.y(); System.out.println(x+y); }}// As of Java 21static void printSum(Object obj) { if (obj instanceof Point(int x, int y)) { System.out.println(x+y); }}5. ZGC
https://openjdk.org/jeps/439
-
ZGC是一款低延迟、高吞吐的JVM垃圾回收器。JDK11试验版本,JDK15变为生产版本,但都是不分代的,所有的对象都存储在一起,每次垃圾回收都要回收所有对象。
在JDK21中区分年轻代和老年代,因为年轻代的对象存活时间更短,所以 通过提高收集年轻代的对象的频率迅速释放JVM内存。
-
默认不开启ZGC,可以使用以下命令开启
java -XX:+UseZGC -XX:+ZGenerational
6. 准备禁用动态代理(Prepare to Disallow the Dynamic Loading of Agents)
https://openjdk.org/jeps/451
- 当代理被动态加载到运行中的 JVM 时发出警告。这些警告的目的是让用户做好准备,以便在未来的版本中默认禁止动态加载代理。
动态代理允许开发人员在运行时修改和监视Java应用程序,存在潜在的安全风险,例如窃取敏感信息、篡改数据等。因此,为了加强Java应用程序的安全性,限制动态加载代理的使用是有必要的。
WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warningWARNING: If a serviceability tool is not in use, please run with -Djdk.instrument.traceUsage for more informationWARNING: Dynamic loading of agents will be disallowed by default in a future release
- 当代理被动态加载到运行中的 JVM 时发出警告。这些警告的目的是让用户做好准备,以便在未来的版本中默认禁止动态加载代理。
- JDK21之后
- Sequenced Collections是一种具有确定出现顺序的集合。提供了处理集合第一个和最后一个元素以及反转集合的简单方法。
- 虚拟线程在block后,会与平台线程解绑,然后加入任务列表排队,等待分配给平台线程
- VirtualThread[#22]/runnable@ForkJoinPool-1-worker-2表示VirtualThread[#22]这个虚拟线程依赖于平台线程ForkJoinPool-1-worker-2,这里我在VM参数中添加了-Djdk.virtualThreadScheduler.maxPoolSize=2 -Djdk.virtualThreadScheduler.parallelism=2,限制平台线程最大2个,所以只能会看到ForkJoinPool-1-worker-1和ForkJoinPool-1-worker-2两个平台线程。
- 通过25号虚拟线程可以看出,阻塞前后使用的平台线程发生过切换
- 打印
- 虚拟线程是工作在平台线程之上的,虚拟线程的数量可以远大于操作系统线程的数量,多个虚拟线程挂载在一个平台线程上,一个平台线程可以在不同的时间执行不同的虚拟线程,当虚拟线程被阻塞或等待时,平台线程可以切换到执行另一个虚拟线程。
上一篇:ps怎么打造飘散效果?