likes
comments
collection
share

【翻译】JEP 444:虚拟线程登陆JDK 21,开创并发新时代

作者站长头像
站长
· 阅读数 23

原文:JEP 444: Virtual Threads Arrive in JDK 21, Ushering a New Era of Concurrency 作者:A N M Bazlur Rahman 发布时间:2023年4月9日

JEP 444,虚拟线程,在 JDK 21 中从候选状态提升为建议目标状态。此功能提供了虚拟线程,即轻量级线程,可显著减少在 Java 平台上编写、维护和观察高吞吐量并发应用程序的工作量。此 JEP 打算根据前两轮预览版的反馈最终确定此功能:JEP 436,虚拟线程(第二预览版),以 JDK 20 形式提供;和 JEP 425,虚拟线程(预览版),以 JDK 19 形式提供。

有了这个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;
        });
    });
}

JDK 现在可以在少量操作系统 (OS) 线程上运行多达 10 000 个并发虚拟线程(少至一个),以执行上述涉及休眠一秒钟的简单代码。

虚拟线程设计为使用线程局部变量和可继承的线程局部变量,就像平台线程一样。但是,由于可以创建大量虚拟线程,开发人员应谨慎使用线程局部变量。为了帮助迁移到虚拟线程,JDK 提供了一个系统属性 jdk.traceVirtualThreadLocals,当虚拟线程设置任何线程局部变量的值时,该属性会触发堆栈跟踪。

java.util.concurrent 软件包现在包括对虚拟线程的支持。LockSupport API 已更新为可以正常停放和取消寄存虚拟线程,从而使使用 (比如LocksSemaphoresblocking queues)的 API 能够与虚拟线程无缝运行。Executors.newThreadPerTaskExecutor(ThreadFactory)Executors.newVirtualThreadPerTaskExecutor() 方法提供了一个ExecutorService,为每个任务创建一个新线程,使用线程池和ExecutorService.LockSupport来便于迁移和与现有代码的互操作性。

java.net 和 java.nio.channels 软件包中的网络API现在支持虚拟线程,从而提高了并发应用程序的效率。虚拟线程上的阻塞操作释放了底层平台线程,而SocketServerSocket 和 DatagramSocket类中的 I/O 方法已变为interruptible。此更新为使用并发应用程序的 Java 开发人员提供了一致的行为和改进的性能。

java.io 包(为字节和字符流提供 API)已更新,以避免在虚拟线程中使用时固定。固定在虚拟线程中是指轻量级线程被“卡”到特定的平台线程,由于阻塞操作而限制了并发性和灵活性。BufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriterPrintStream 和 PrintWriter 现在在直接使用时使用显式锁而不是 monitor。InputStreamReader 和 OutputStreamWriter 使用的流解码器和编码器现在使用相同的锁。

Java Native Interface(JNI)引入了一个新函数 IsVirtualThread 来测试对象是否为虚拟线程。否则,JNI 规范保持不变。

由 JVM 工具接口 (JVM TI)、Java 调试线路协议 (JDWP) 和 Java 调试接口 (JDI) 组成的调试体系结构已更新为支持虚拟线程。所有三个接口现在都支持虚拟线程,并添加了新功能和方法来处理线程开始和结束事件以及虚拟线程的批量挂起和恢复。

JDK 飞行记录器 (JFR) 现在通过新事件支持虚拟线程,比如jdk.VirtualThreadStartjdk.VirtualThreadEndjdk.VirtualThreadPinnedjdk.VirtualThreadSubmitFailed 。通过这些事件,可以深入了解应用程序中虚拟线程的行为。

Java Management Extensions (JMX) 将继续通过 ThreadMXBean 接口仅支持平台线程。HotSpotDiagnosticsMXBean 接口中的新方法会生成新样式的线程转储以支持虚拟线程。

虽然虚拟线程带来了显著的性能改进,但开发人员应注意由于现有 API 及其实现的更改而导致的兼容性风险。其中一些风险包括对 java.io 包中的内部锁定协议的修订,以及可能会影响扩展 Thread 类的代码的源和二进制不兼容的更改。

虚拟线程标志着 Java 支持高度并发和可扩展应用程序的重要里程碑。借助更高效、更轻量级的线程模型,开发人员现在可以轻松处理数百万个任务,并更好地利用系统资源。开发人员可以利用有关JEP 425的更多细节,这些细节可以在InfoQ的新闻报道JEP咖啡馆的屏幕上找到,José Paumard是OracleJava平台组的Java开发人员倡导者。