JKD 21 中出现虚拟线程,开创并发新纪元
JEP 444 虚拟线程已从 JDK 21 的候选(Candidate)升至建议实现 状态(Proposed to Target)。该功能提供虚拟线程这一轻量级线程,可大幅削减在 Java 平台上高吞吐量并发应用的编写、维护及观察的工作量。根据在 JDK 20 中交付的 JEP 436 虚拟线程(第二次预览),在 JDK 19 中交付的 JEP 425 虚拟线程(预览),这前两轮的反馈,本次 JEP 预计将最终敲定该项功能。
随着这一 JEP 的加入,Java 将有传统线程(又名平台线程)和虚拟线程两种类型的线程存在。平台线程是对操作系统线程的一对一封装,而虚拟线程则是由 JDK 所提供的轻量级实现,可在同一条操作系统线程中运行多条虚拟线程。虚拟线程提供了比平台线程更为有效的替代方案,允许开发者以肉眼可见的低开销处理大量任务,与此同时,这类线程也受益于增强的性能和资源利用率,提供对已有 Java 代码的兼容性和无缝迁移路径。以下面这段代码为例:
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10_000).forEach(i -> {
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return i;
});
});
}
目前,在低至一个的操作系统(OS)线程上,JDK 可运行高达一万个并发虚拟线程,执行这段让程序睡眠一秒钟的简单代码。
虚拟线程的设计让其可与线程本地的变量、可继承线程本地的变量共同运作,这点与平台线程相同。但由于虚拟线程的可创建数量上限非常高,开发者在使用线程本地变量时应当多留心。至于虚拟线程的迁移,JDK 所提供的系统属性 jdk.traceVirtualThreadLocals
可在虚拟线程设置任何线程本地变量值时,触发堆栈跟踪。
程序包 java.util.concurrent
现已包含对虚拟线程的支持。LockSupport
API 也已更新,可优雅暂停(park)或恢复(unpark)虚拟线程,允许 锁(Lock)、Semaphores、阻塞队列 等使用 LockSupport
的 API 与虚拟线程无缝连接。
其中,Executors.newThreadPerTaskExecutor(ThreadFactory)
和Executors.newVirtualThreadPerTaskExecutor()
方法,可通过 ExecutorService
为每个任务创建一个新线程,在利好迁移的同时,也让使用线程池的已有代码具备与 ExecutorService
的互操作性。
在 java.net
和 java.nio.channels
包中的网络 API 现已支持虚拟线程,使并发应用更为高效。虚拟线程中的阻塞操作可释放底层平台线程,而 Socket
、ServerSocket
及 DatagramSocket
类中的 I/O 方法也已改为可中断)。本次更新为并发应用的 Java 开发者们提供了更好的一致性行为和性能。
用于字节流和字符 API 的 java.io
包也已更新,避免在使用虚拟线程时被锁定。虚拟线程中的锁定是指轻量级线程“被困”于某个平台线程而导致的阻塞操作,从而限制了线程的并发性和灵活性。此外, BufferedInputStream
、BufferedOutputStream
、BufferedReader
、BufferedWriter
、PrintStream
及 PrintWriter
在直接使用时,已将原先的监视器锁改为显式锁。InputStreamReader
与 PrintWriter
所使用的流解码器与编码器现也已改为与其对应的流关闭 InputStreamReader
或 OutputStreamWriter
使用相同的锁。
Java 本地接口(JNI)引入用于检测对象是否为虚拟线程的新函数 IsVirtualThread
。除此之外,JNI 规范没有其他变化。
由 JVM 工具接口(JVM TI)、Java 调试协议(JDWP),及 Java 调试接口所(JDI)组成的调试架构现已更新,可支持虚拟线程。其中三个接口均已支持虚拟线程,且增加了用于处理线程开始和结束事件、虚拟线程批量暂停恢复的新功能和方法。
JDK 飞行记录器(JFR)现已支持虚拟线程的新事件,诸如 jdk.VirtualThreadStart
、jdk.VirtualThreadEnd
、jdk.VirtualThreadPinned
,以及jdk.VirtualThreadSubmitFailed
。上述这些事件均提供了对应用程序内虚拟线程行为的洞察力。
Java 管理扩展(JMX)仍旧通过ThreadMXBean
接口 仅 支持平台线程。HotSpotDiagnosticsMXBean
接口中新方法将生成该新增线程类型的转储,从而支持虚拟线程。
虽然虚拟线程为我们带来了显著的性能改善,但开发者仍应注意对已有 API 及其实现的更改可能造成的兼容性问题,如对 java.io
包中内部锁协议的修订,任何扩展 Thread
类的代码源码可能存在与二进制不兼容的问题,等等。
虚拟线程的引入标志着 Java 在支持高并发和可扩展应用道路上的里程碑式进展。随着这一更为高效且更为轻量级的线程模型的出现,开发者现已可以轻松处理数以百万级的任务量,对系统资源的利用也更为充分。关于 JEP 425 的更多开发者细节,请参见 InfoQ 新闻及 Oracle 公司 Java 平台组的 Java 开发者倡导 José Paumard 在 JEP Café 的演讲截屏。
原文链接:
JEP 444: Virtual Threads Arrive in JDK 21, Ushering a New Era of Concurrency(https://www.infoq.com/news/2023/04/virtual-threads-arrives-jdk21/)
相关阅读:
Java 近期新闻:字符串模板、Quarkus、Open Liberty、PrimeFaces、JobRunr、Devnexus 2023(https://www.infoq.cn/article/gB3ToN16f0iPC3tvdpDZ)
加入有序集合,Java 集合框架变得更加完善 (https://www.infoq.cn/article/PyfmlboNJMKzlhZTwDL3)
声明:本文为 InfoQ 翻译,未经许可禁止转载。
点击底部阅读原文访问 InfoQ 官网,获取更多精彩内容!
微信扫码关注该文公众号作者