Redian新闻
>
什么是虚拟线程?一次启1000万个会OOM吗?

什么是虚拟线程?一次启1000万个会OOM吗?

公众号新闻

什么是虚拟线程

虚拟线程是在Java并发领域添加的一个新概念,那么虚拟线程到底是做什么用的呢?

根据JEP中的内容告诉我们,虚拟线程是一种轻量级线程,可以显著地帮助我们减少编写、维护、观察高吞吐量应用程序的工作量。它的实现目标有以下几点:

  1. 每个请求一个线程风格编写的程序,能够以接近最佳硬件利用率进行扩展。

什么是每个请求一个线程的风格?

对于HTTP服务器来说,这意味着每个HTTP请求都由它自己的线程处理。对于关系型数据库服务器来说,这意味着每个SQL事务也都由它自己的线程处理。如果您曾经使用过 Java EE 服务器,那么它就是这样工作的。所以,什么是每个请求一个线程的风格就是:一个请求 = 一个事务 = 一个线程

那么,这个模型的成本是多少呢? 要了解这个成本,您需要了解 Java 中线程的成本。平台线程和 CPU 使用率的成本。

Java 线程是在 Java 的早期版本中创建的,属于平台线程,也称为操作系统线程上的薄包装器。关于它们,您需要了解两件事。

  • 平台线程需要将其调用堆栈存储在内存中
  • 它是系统资源,启动平台线程大约需要一毫秒

事实上,平台线程是一种相当昂贵的资源。如何利用此类线程优化硬件利用率呢?

假设您的应用程序有 16 GB 的可用内存。除以 20 MB 的线程大小,这样的机器上就有 800 个线程的空间。假设这些线程正在执行一些 I/O,就像访问网络上的资源一样。假设该资源在 100 毫秒内被访问。准备请求和处理响应将在 10 纳秒的时间内完成。假设所有这些内存计算需要 1000 纳秒。这意味着在准备请求和处理响应之间存在一个大约 100000 的因素,以及获得响应所需的时间,在此期间您的线程就在那里什么都不做。所以如果你有 800 个这样的线程,那么CPU利用率只有可怜的0.8%。

如果你将内存加倍到 32 GB,那么CPU利用率可以达到1.3%,但这仍然很低。

反过来思考下,如果我们希望达到90%的CPU利用率。那么就需要 90000 个线程,启动它们需要 90秒,同时,还要消耗 1.8 TB 的内存。

很明显,平台线程的成本太高,无法以接近最佳的硬件利用率进行扩展。因此,我们需要另一种线程模型来解决这样的问题。

  1. 使基于经典 Java 线程的现有代码能够以最小更改代价来使用虚拟线程

这一目标意味着可以把经典线程做的所有事情,轻松的转换为虚拟线程的处理方式来完成。这里涵盖了几个关键点。

  • 虚拟线程可以运行任何Java代码或任何本机代码。
  • 你不需要学习任何新概念。
  • 但你需要忘掉某些想法,比如:
    • 虚拟线程很便宜,比传统平台线程便宜大约 1,000 倍。
    • 阻塞虚拟线程的成本也很低,因此试图避免阻塞虚拟线程是没有用的。
    • 编写经典的阻塞代码是可以的,这是一个好消息,因为阻塞代码比异步代码更容易编写。此时,您可能想知道,池化虚拟线程是个好主意吗?嗯,答案是否定的。不要那样做。你只是在浪费时间。

关于虚拟线程还有两个好消息:线程局部变量也以同样的方式工作;同步也有效。关于同步有几件事需要说一下。虚拟线程仍然运行在平台线程之上,下面还有一个平台线程。不过,这个虚拟线程可以与其平台线程分离,以便这个平台线程可以运行另一个虚拟线程。什么时候才能脱离呢?虚拟线程一旦阻塞就可以与其平台线程分离。它可能会在I/O操作或同步操作上被阻止,或者可能会被置于睡眠状态。如果虚拟线程正在同步块内执行某些代码,则它无法与其平台线程分离。

因此,在运行此同步代码块期间,它会阻塞平台线程。如果这个时间很短,那也没关系。无需恐慌,也无需采取任何措施来防止这种情况发生。如果这个时间很长,也就是说,如果它正在做一些长时间的I/O操作,那么情况就不太好了。您可以通过简单地将对 synchronized 的调用替换为可重入锁来防止这种情况发生。

深入研究编码

关于如何创建虚拟线程,在之前的Java 21新特性虚拟线程中有提到。通过Thread.ofVirtual()即可,比如:

Thread.ofVirtual()
        .name("didispace-virtual-thread")
        .start(runnable);

Tips:如果要创建平台线程,则可使用:Thread.ofPlatform()

虚拟线程工作在平台线程之上。您可能认为没有任何性能提升,只是产生了开销。那么到底是怎么回事呢?关于虚拟线程还有更多内容。下面一起来看看这段代码是如何运行的。

这段代码中,使用了流模式创建 10 个虚拟的、未启动的线程。这些线程正在运行的任务只是打印当前线程。然后,让它们休眠 10 毫秒,接着再次打印线程的名称。最后,启动这些未启动的线程并调用 join 方法以确保所有内容都可以在控制台上看到。

那么运行这段代码,您会发现这里发生了一些真正意想不到的事情。

这个ForkJoinPool的线程7,当它从睡眠状态回来时,它并没有继续运行在原来的平台线程上,而是跳转到了另外一个平台线程。如果您在自己的计算机上执行此操作,请确保启动足够的虚拟线程,因为您可能不会仅使用一两个线程来观察到这一点。

它在幕后是如何工作的

事实上,当虚拟线程由于某些操作而被阻塞时,相应的堆栈就会从其运行的平台线程移动到堆内存中。所以,现在这个平台线程可以自由地运行另一个虚拟线程。当这个任务收到可以继续运行的信号时,它的堆栈就会从堆移回平台线程,但不一定相同。所以,这就是阻塞虚拟线程的代价,将该虚拟线程的堆栈移动到主内存并返回。阻塞虚拟线程并不是免费无开销的,但它比阻塞平台线程要划算得多。

Tips:这段逻辑视频里有图形化的解释,推荐结合视频动画观看,会更容易理解。

令人高兴的是,JDK 的所有阻塞操作都已被重构以利用它。其中包括I/O操作、同步和Thread.sleep

需要多少平台线程来运行虚拟线程

关于这个问题,我们可以测试一下。让我创建虚拟线程并收集所有相应的平台线程名称。

该代码基本上启动了五个虚拟线程,然后使用一些代码提取池名称和平台线程名称。最后,它只是打印不同的统计信息、运行此代码所需的时间、CPU 上的核心数量、线程池数量,以及平台线程的数量。

那么让我运行这段代码,可以看到如下结果:

对于 5 个虚拟线程,它使用 3 个平台线程并花费 2 毫秒。

让我使用 10 个虚拟线程并再次运行代码。

对于 10 个线程,它仍然使用 3 个平台线程并花费了 4 毫秒。

让我使用 100 个虚拟线程并再次运行代码。

现在它使用 7 个平台线程。

让我们看看 1,000 个虚拟线程会发生什么。

它仍然使用 7 个平台线程。

试试10万个虚拟线程怎么样?

现在它使用 8 个平台线程,花费了 156 毫秒。

顺便说一句,即使这些线程没有做太多事情,只是一些字符串操作和在并发集中添加元素,您也可以看到运行所有这些线程只需要 156 毫秒。

现在让我增加到 100 万个线程。

花费了不到一秒的时间,并且仍然使用 8 个平台线程。

如果您学习过程中如遇困难?可以加入我们超高质量的技术交流群,参与交流与讨论,更好的学习与进步!另外,不要走开,关注我!持续更新Java新特性专栏!

启动1000万个虚拟线程

我们尝试启动 1000 万个虚拟线程怎么样?你曾经尝试过这样做吗?在您的机器上启动 1000 万个平台线程?嗯,通常这是不可能的,但是使用虚拟线程,我们也许能够做到。我们可以获得如下结果:

这还只是在一台旧笔记本电脑上测试的结果,只需要不到 7 秒的时间,这真是太棒了!

这就是Java 中的虚拟线程!是不是很棒?那么,你是否已经开始升级Java 21并开始使用此特性来提升你的应用性能了呢?留言区一起聊聊吧。

往期推荐



no-GIL Python,启动!
Linus曾给Windows 7热情点赞
云原生 IDE 将成为常态




活动推荐

10 月 28 日,本周六,源创会苏州站暨 Techo TVP 技术沙龙将正式拉开帷幕。

这一次,我们以“寻宝 AI 时代”为主题,希望能给每一位开发者新的启发,一起在 AI 新时代更上一层楼。同时,我们将沙龙地点定在了轰趴馆,希望各位玩得开心!

快扫描下方二维码,或点击文末“阅读原文”即刻报名 🎁🎁


阅读原文立即报名>>

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
5G RedCap在未来10多年将经历什么样的发展历程?红色日记 2.26-28给诸葛亮100万个大学生,刚跑出大营累趴50万开了个会后,我开始思考:我真的是产品经理吗?我们的一年(7)喧宾夺主的VLA华硕 TRX50 主板价格曝光:约 8000 元,支持线程撕裂者 7000 处理器什么是网络间谍行为?遇到了该怎么办?一文了解英特尔酷睿 Ultra 7 1002H 处理器现身:16 核 22 线程,睿频 5GHz全球首个!安永联合微软,开启10小时速通ESG项目去儿子家养老Spring Framework 6.1正式GA,兼容虚拟线程和JDK 21[汽车] 告别陪伴了我6年的Zoom~zoom——马自达阿特兹6年用车体验分享什么是异化?什么是物化?爆火的服务设计,为什么没有本科课程?※ ※ 這世界有那麽多人 ※ ※ 小艾生日快乐!!!James只用了3小时,我就“扒光”了一个女生,下一个会是你吗?The Bookstore Giving Shanghai’s Women a Room of Their Own一个进程最多可以创建多少个线程?【Locker Room】Locker Room运动上新!女篮、飞盘&腰旗橄榄球,你准备好了吗?Spring Boot虚拟线程的性能还不如Webflux?Spring Boot 3.2 正式发布,开箱即用的虚拟线程和 GraalVM,尝鲜一下!人生最好的事就是虚惊一场从虚拟偶像到虚拟主播,一场TO C到TO B生意的大迁徙独家视频|宋方金演讲:回首往事,不过是虚惊一场什么是虚拟机? | Linux 中国从数字人彩铃到虚拟仿真课堂,中国移动江西虚拟现实实践“动真情”十大免费虚拟号码平台推荐 | 虚拟手机号,再也不怕收到诈骗电话了绝了!加个会转的圆,PPT直接高级100倍!Java 21:下一个LTS版本,提供了虚拟线程、记录模式和模式匹配泼天的富贵轮到Costco南瓜派?一周卖出1.6万个...信息量好大!马云卖股套现63亿,市值蒸发超2700亿!阿里杀崩港股,抖音概念狂欢,冲击20%涨停!短剧是风口还是虚火?这个中秋,让我们再次启程工信部:我国5G行业虚拟专网超2万个“十万个为什么”打造的十万个冷知识
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。