Java 虚拟线程简介
Java 虚拟线程是 Java 19 中引入的一项新功能,允许开发人员创建轻量级线程,也称为纤程或者协程。这可以提高 Java 应用程序的可伸缩性和效率,特别是那些需要处理大量客户端连接或并发请求的应用程序。
虚拟线程是使用一种称为 Continuation Passing Style,简称 CPS 的技术来实现的。CPS 是一种编程范例,其涉及在代码的不同部分之间传递程序的控制流,而不是依赖于中央执行线程。这允许比传统线程更有效地创建和管理虚拟线程。你可以通过本文了解更多细节。
虚拟线程与线程的区别
虚拟线程在几个方面与传统的 Java 线程不同。首先,它们是使用一个名为 VirtualThreadFactory 的新 API 创建的,该 API 为管理和调度虚拟线程提供了一个简化的接口。其次,与传统线程相比,虚拟线程的内存开销要低得多,这使得创建更多的线程而不会耗尽系统资源成为可能。最后,它们被设计为与现有的 Java 代码无缝衔接地工作,因此开发人员可以开始使用虚拟线程,而不必重写整个应用程序。
若要创建虚拟线程,可以使用 VirtualThreadFactory 类,该类提供了几种用于创建具有不同特征的虚拟线程的工厂方法。例如,你可以创建一个执行 Runnable 或 Callable 任务的虚拟线程,或者创建一个无限期运行直到显式停止的虚拟线程。
下面是如何创建虚拟线程的示例:
在这个例子中,我们创建了一个新的虚拟线程工厂,它产生守护进程线程(即,在后台运行并且不会阻止 JVM 关闭的线程),然后使用它创建一个新的虚拟线程,该线程打印 Hello,world 到控制台。
虚拟线程比传统线程有很多优点,但也有一些缺点。例如,它们可能不适合需要对线程调度或同步进行细粒度控制的应用程序,并且它们可能无法与依赖传统线程的第三方库很好地配合使用。尽管如此,Java 虚拟线程代表了 Java 并发性的一个令人兴奋的新发展,它可能会对开发人员在未来几年编写并发代码的方式产生重大影响。
如何创建虚拟线程
要在 Java 中创建虚拟线程,可以使用 java.lang
包中提供的 VirtualThreadFactory
类。以下是创建虚拟线程的基本步骤:
使用
VirtualThreadFactory.builder()
方法创建VirtualThreadFactory
类的实例使用构建器方法,使用任何所需选项配置工厂。例如,可以设置线程名前缀、线程是否应该是守护程序线程,或者它们是否应该是用户或系统线程组的一部分
使用
VirtualThreadFactory
的newThread()
方法创建一个新的虚拟线程。此方法接受一个Runnable
或Callable
对象,该对象指定线程要执行的任务调用虚拟线程的
start()
方法开始执行
下面是一个如何使用 VirtualThreadFactory
类创建虚拟线程的示例:
在上面的 Demo 中,我们使用 builder 方法创建了一个带有几个选项的 VirtualThreadFactory
实例。然后,我们使用工厂的 newThread()
方法创建一个新的虚拟线程,并传递一个 lambda 表达式,该表达式定义了线程要执行的代码。最后,我们调用虚拟线程的 start()
方法来开始执行。
请注意,虚拟线程的内存占用比常规线程小得多,因此你可以创建更多的虚拟线程,而不会耗尽系统资源。但是,用户仍然应该注意应用程序中的线程总数,并确保没有创建太多线程,否则会导致争用和性能降低。
虚拟线程的优点和缺点
Java 虚拟线程(JVT)提供了几个优于传统 Java 线程的优点。以下是一些主要优势:
更低的内存开销:虚拟线程的内存占用比传统线程小得多,这意味着用户可以创建更多的虚拟线程,而不会消耗过多的内存。这是因为虚拟线程与其他线程共享一个堆栈,从而减少了每个线程所需的内存量。
改进的可扩展性:由于虚拟线程具有较低的内存开销,因此它们比传统线程更具可伸缩性。程序可以创建更多的虚拟线程,而不会遇到内存限制,这有助于提高应用程序的性能。
更好地利用系统资源:使用虚拟线程,可以创建更多的线程,而不会耗尽系统资源,如 CPU 时间、线程句柄和内核级线程。
更简单的编程模型:虚拟线程提供了比传统线程更简单、更自然的编程模型。用户可以使用熟悉的控制结构(如循环和条件)来编写在虚拟线程上并发运行的代码。这可以使并发代码的编写和推理变得更容易。
与现有代码无缝集成:虚拟线程被设计为与现有的 Java 代码无缝地工作。可以将它们与其他并发结构(如 executors、CompletableFuture 和 Reactive Streams)结合使用,而无需重写整个应用程序。
虽然 Java 虚拟线程(JVT)提供了一些优点,但它们也有一些开发人员应该注意的潜在缺点。以下是一些主要的缺点:
兼容性问题:一些现有的 Java 库和框架可能与虚拟线程不兼容,因为它们可能依赖于特定于传统线程的假设或 API。这可能会使在现有代码库中采用虚拟线程变得困难,或者需要修改第三方库才能使用虚拟线程。
同步挑战:虚拟线程共享单个底层操作系统线程,这意味着虚拟线程之间的同步可能比传统线程更具挑战性。开发人员可能需要仔细设计他们的同步策略,以避免竞争条件或其他同步问题。
调试和分析:调试和分析虚拟线程可能比传统线程更具挑战性,因为它们共享相同的底层线程 ID 和其他线程相关属性。这可能会使识别和诊断与并发或线程争用相关的问题变得更加困难。
对调度的有限控制:使用虚拟线程时,Java 运行时负责调度线程,这可能会限制开发人员对线程调度的控制级别。虽然 Java 运行时旨在提供虚拟线程的高效调度,但在某些情况下可能需要更细粒度的控制。
性能权衡:虽然虚拟线程比传统线程更轻量级,但它们可能会有一些性能折衷。例如,虚拟线程之间的切换可能比传统线程慢,这可能会影响某些类型的应用程序的性能。
虚拟线程性能影响
Java 虚拟线程(JVT)可以对某些类型的应用程序的性能产生积极的影响,但其影响可能会因特定的用例而异。以下是可能影响虚拟线程性能的一些因素:
任务大小:虚拟线程针对执行小型、短期任务进行了优化。如果应用程序有许多可以并发执行的小任务,则虚拟线程可以提供比传统线程更大的性能提升。
竞争:如果应用程序的线程之间存在高度竞争,虚拟线程可能有助于减少争用并提高性能。这是因为虚拟线程比传统线程更轻量级,并且可以更快地创建和销毁。
同步:虚拟线程之间的同步可能比传统线程更具挑战性,设计不当的同步策略可能导致争用和性能下降。开发人员应该仔细设计他们的同步策略,以确保虚拟线程之间高效和有效的同步。
I/O 操作:虚拟线程对于执行大量 I/O 操作(如网络或数据库操作)的应用程序特别有效。这是因为虚拟线程更适合处理需要等待 I/O 操作完成的任务。
资源利用率:虚拟线程在内存利用率方面比传统线程更有效,这有助于提高应用程序的总体资源利用率。这对于需要在内存资源有限的系统上运行的应用程序尤其重要。
总的来说,虚拟线程的性能影响将取决于特定的用例和正在执行的任务的性质。开发人员在决定是否在应用程序中使用虚拟线程之前,应该仔细评估虚拟线程的潜在好处和利弊。通常,虚拟线程可以为具有许多小任务或 I/O 操作的应用程序提供显著的性能提升,但可能不会为具有长时间运行任务或高度同步的应用程序提供同样多的好处。
总结发言
Java 虚拟线程是 Java 编程语言中一个相对较新的特性,它提供了一种管理轻量级线程的有效方法。它们被设计成比传统线程更高效,传统线程可能相对较重并且可能消耗大量资源。
虚拟线程可用于扩展 Java 应用程序中的线程数量,而不会产生与传统线程相关的开销。这使得它们对于需要处理大量并发连接的应用程序特别有用。
此外,虚拟线程可用于简化异步代码的开发,使用传统线程可能难以编写和维护异步代码。虚拟线程使编写异步执行的代码变得更容易,而不会牺牲性能。
Java 虚拟线程是 Java 编程语言中一个很有前途的发展,随着越来越多的开发人员熟悉它们并开始在应用程序中使用它们,它们可能会变得越来越流行。
版权声明: 本文为 InfoQ 作者【FunTester】的原创文章。
原文链接:【http://xie.infoq.cn/article/5e6725d28809d9f20caf69c3a】。文章转载请联系作者。
评论