虚拟线程是Java的Project Loom项目引入的一种全新线程模型,并随Java 21 LTS正式发布,虚拟线程承诺无与伦比的可扩展性、简化的异步编码和更高效的资源利用。尽管如此,开发人员还必须了解Java虚拟线程的潜在陷阱,特别是固定问题。
本文将探讨固定问题、应对策略,以及开发人员在采用这种新的有前景的并发模型时的关键考虑因素。
虚拟线程的好处
与传统的操作系统线程不同,在内存占用空间和上下文切换开销方面Java虚拟线程都非常轻。一个Java应用程序有可能管理数十万甚至数百万个应用程序,且非常轻松。
虚拟线程允许开发人员编写看起来按顺序和同步的代码,即使有I/O固定操作。这通常消除了对复杂回调驱动或被动编程样式的需求。
采用虚拟线程的应用程序通常可以避免经典Java服务器架构中的瓶颈。开发人员可以期待更好的CPU和内存利用率,这可能会转化为节省基础设施成本。
Java虚拟线程固定问题
然而,虚拟线程并非万能。深入来看,Java运行时将它们映射到称为载波线程的本机操作系统线程池上。这就是固定问题出现的地方。
如果虚拟线程需要执行阻塞代码,例如与同步关键字的传统同步或本机方法调用,它不能像I/O操作那样简单地暂停和生成。相反,虚拟线程被固定在其载波线程上。
固定的虚拟线程可以防止其他虚拟线程使用该载波线程。过于频繁或持久的固定可能会削弱虚拟线程的一些核心可扩展性优势。
如何检查应用程序是否存在固定问题
在大规模迁移到虚拟线程之前,评估固定风险至关重要。以下步骤概述了如何使用Spring来做到这一点。
启用虚拟线程。通常,简单的配置更改就已足够。
spring:
threads:
virtual:
enabled: true
检测问题。接下来,添加以下JVM参数。
–Djdk.tracePinnedThreads=full
注意确定发生固定的堆栈跟踪的日志条目。这些堆栈跟踪揭示了哪些代码部分或外部库可能很麻烦。以下代码片段显示了输出可能的样子。
VirtualThread[#20]/runnable@ForkJoinPool–1–worker–1
VirtualThread[#21]/runnable@ForkJoinPool–1–worker–2 reason:MONITOR
java.base/java.lang.VirtualThread$VThreadContinuation.onPinned(VirtualThread.java:199)
java.base/jdk.internal.vm.Continuation.onPinned0(Continuation.java:393)
java.base/java.lang.VirtualThread.parkNanos(VirtualThread.java:635)
java.base/java.lang.VirtualThread.sleepNanos(VirtualThread.java:812)
java.base/java.lang.Thread.sleepNanos(Thread.java:489)
java.base/java.lang.Thread.sleep(Thread.java:522)
ca.example.myapp.
.ThreadPinnedExample.lambda$main$0(ThreadPinnedExample.java:20) <== monitors:1
java.base/java.lang.VirtualThread.run(VirtualThread.java:329)
VirtualThread[#20]/runnable@ForkJoinPool–1–worker–1
衡量影响。Java Flight Recorder(JFR)是你首选的工具。首先,开始记录。
jcmd <PID> JFR.start duration=200s filename=myrecording.jfr
然后,分析固定持续时间。
jfr print —events jdk.VirtualThreadPinned myrecording.jfr4
解决库更新以外的固定问题
解决固定问题最干净的解决方案可能是将你的依赖项更新为专为虚拟线程优化的版本。全面拥抱Project Loom的项目将用工具(例如ReentrantLock)取代旧的同步机制,以避免固定问题。
如果更新还不可用,另一个解决方案是暂时重组代码。有效的策略包括卸载阻塞操作,以分离传统线程池或重构,以使用非阻塞库和非同步编码模式。
另一种选择是使用信号量,信号量可以通过限制可以执行阻止操作的并发执行虚拟线程的数量来充当门卫。然而,在这里要格外小心。如果你将许可证数量设置得太低,这可能会严重阻碍吞吐量,并抵消虚拟线程的优势。具有讽刺意味的是,人们可能会限制应用程序运行比经典线程池更少的并发任务。
Java中的虚拟线程:需要记住的要点
当你评估虚拟线程时,请记住几个关键的要点。
1. 生态系统的演变
很多流行的库仍在追赶虚拟线程。它们可能依赖于阻止同步原语,这些原语无意中固定虚拟线程。随着Project Loom的采用率增加,这可能会随着时间的推移而改善,但你选择的库时要注意这一点。
2. 资源权衡
通过使用虚拟线程,创建大量并发线程的潜力可能会无意中重新引入经典线程池旨在解决的资源限制。为了防止不受控制的资源枯竭,明智地使用信号量、特定阻塞任务的线程池或其他限制机制至关重要。
3. 生态系统兼容性
框架和语言以不同的方式与虚拟线程进行交互。注意兼容性问题。例如,某些Kotlin coroutine模式在特定条件下可能会有固定的风险。请仔细研究你的技术如何与虚拟线程堆叠。
4. 指标
当你尝试虚拟线程时,请关注这些关键绩效指标:
- 中央处理器性能。验证预期的可扩展性收益是否实现,并最大限度地减少有害的固定。
- 内存和垃圾收集。虚拟线程可能会减少整体进程内存,但更多线程样结构可能需要更加关注垃圾收集模式。准备好调整堆大小和潜在的垃圾收集调整参数。
- 延迟和吞吐量。测量端到端性能对应用程序响应性的影响以及系统每秒可以处理的请求数量。
我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。
我原创,你原创,我们的内容世界才会更加精彩!
【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】
微信公众号
TechTarget
官方微博
TechTarget中国
翻译
相关推荐
-
对最终用户而言,虚拟机安全吗?
虚拟机可为用户工作会话提供安全隔离,但人们不太确定这项技术的安全性。在企业部署虚拟机之前,管理层必须了解这项技 […]
-
最新VMware产品发布让博通面临挑战
分析师表示,很多企业仍然不确定是否应该继续使用Broadcom的VMware,该供应商最近对其混合云平台做出重 […]
-
云应用程序应该选择Docker容器还是虚拟机?
容器对于虚拟机,就像虚拟机对于物理服务器,在规模、速度和灵活性方面,它们都是规则改变者。企业应该在概念层面上熟 […]
-
HPE将为GreenLake私有云提供KVM虚拟化
HPE GreenLake for Private Cloud客户将很快可以访问完整的虚拟化堆栈,其中包括HP […]