当前位置:Java -> Java的未来:JDK 21中的虚拟线程及其影响
JDK 21,于2023年9月19日发布,标志着Java进化历程中的重要里程碑。这是一个长期支持(LTS)版本,确保至少获得8年的来自Oracle的稳定性和支持。在这个版本中,Java开发人员将遇到一些新功能,包括虚拟线程、记录模式、开关语句的模式匹配、外部函数和内存API以及ZGC垃圾收集器。
在这些功能中,虚拟线程在并发Java应用程序的世界中脱颖而出,成为了一个改变者。虚拟线程有潜力彻底改变开发人员编写和管理并发代码的方式。它们提供了非凡的优势,使其非常适合高吞吐量的并发应用程序。
虚拟线程为我们带来了一些优势,使其与传统平台线程有所区别:
为了理解虚拟线程的重要性,让我们简要地了解三种类型的线程:
1. 操作系统线程(本地线程): 这些是现代操作系统中的执行基本单元。每个操作系统线程都有自己的栈、程序计数器和寄存器集,由操作系统内核管理。
2. 平台线程(传统Java线程): 平台线程建立在操作系统线程之上,由Java虚拟机(JVM)管理。它们提供更有效的调度和资源利用。平台线程是java.lang.Thread的实例,按照传统方式实现,即在操作系统线程的周围做了薄薄的封装。
3. 虚拟线程: 虚拟线程是java.lang.Thread的实例,不绑定于特定的操作系统线程。多个虚拟线程可以由单个操作系统线程服务。虚拟线程甚至比传统线程更轻量级和更高效,并可以用于改进并发Java应用程序的性能、可伸缩性和可靠性。
线程是并发服务器应用程序的构建模块,几乎已经成为Java近三十年的重要部分。不幸的是,传统的Java线程创建和维护成本高昂。可用线程的数量有限,因为JDK将线程实现为操作系统(OS)线程的封装。由于OS线程成本高昂,我们无法拥有太多线程,这使得该实现不适合每个请求一个线程的模式,从而限制了Java服务器可以处理的并发请求数量,影响了服务器应用程序的可伸缩性。
随着时间的推移,为了能够扩展并充分利用硬件,Java开发人员从每个请求一个线程的模式过渡到了线程共享的模式。在线程共享中,请求处理代码在等待另一个I/O操作完成时将其线程返回到线程池,以便线程可以服务于其他请求,而不是从头到尾在一个线程上处理请求。
这种细粒度的共享可以节省线程,但需要异步编程技术。异步编程是一种复杂且易出错的提高可伸缩性的方式,它与常见的Java服务器应用程序中常用的每个请求一个线程的模式不兼容。
虚拟线程提供了一个引人注目的解决方案,可以在增强并发性的同时保留以请求为基础的线程风格。它们不受限于特定的操作系统线程,可以实现更大的并发性。虚拟线程只在CPU密集型任务期间消耗操作系统线程。当它们遇到阻塞的I/O操作时,它们会自动挂起,而不会垄断操作系统线程。创建和管理虚拟线程非常简单,无需使用池。
虚拟线程生命周期短暂,执行特定任务,且数量众多。平台线程则是重量级的,生命周期长,可能需要池化。使用虚拟线程可以在优化硬件利用率的同时保持以请求为基础的线程风格。
值得注意的是,JDK 21的目标不是取代传统的线程实现,而是提供高效的替代方案。开发人员可以根据特定需求选择虚拟线程或平台线程,保持灵活性。
下面是一个简单的示例,展示了虚拟线程的强大之处:
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10_000).forEach(i -> {
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return i;
});
});
// Wait for all tasks to complete.
} // The executor is automatically closed, and it waits for task completion.
在这个示例中,现代硬件可以高效地同时处理10,000个虚拟线程,执行简单的代码。在幕后,JDK可以高效地管理这些虚拟线程,优化资源利用率。
Java开发人员长期以来一直依赖线程进行并发编程。随着JDK 21引入虚拟线程,实现高并发性并保持熟悉的编程风格变得更加容易。虚拟线程特别适用于处理大量用户请求的服务器应用程序,在不断变化的环境中提供了效率和可伸缩性。
推荐阅读: 程序员如何成为自由职业者
本文链接: Java的未来:JDK 21中的虚拟线程及其影响