java21中一次启动1000万个虚拟线程要多久?需要多少平台线程?

 什么是虚拟线程

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

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

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

 

 

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

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

 

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

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

 

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

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

 

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

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

 

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

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

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

 

 

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

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

启动1000万个虚拟线程 

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

图片

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

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

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/157175.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

为什么别人年薪30W+?同样为测试人,“我“的测试之路...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 1、软件测试员&am…

Go 上下文 context.Context

Go语言中的上下文(Context)是一种用于在 Goroutines 之间传递取消信号、截止时间和其他请求范围值的标准方式。context 包提供了 Context 类型和一些相关的函数,用于在并发程序中有效地传递上下文信息。 在Go语言中,上下文通常用于…

Minio - 多节点多驱动器安装部署

先决条件 网络互通 MinIO集群中的节点的网络需要互相双向互通。 MinIO API默认端口9000 MinIO console默认端口9001 MinIO强烈建议使用负载均衡器来管理与集群的连接。负载均衡器策略使用“最小连接数”逻辑,因为在部署中任何 MinIO 节点都可以接收、路由或处理…

什么是软件定制开发?|app网站小程序定制

什么是软件定制开发?|app网站小程序定制 软件定制开发是根据客户的特定需求,为其量身定制开发软件解决方案的全过程。与市面上已有的通用软件不同,软件定制开发可以满足客户在业务流程、功能要求、用户界面等方面的个性化需求。 软件定制开发…

Redis链表

前言 链表作为一种常见的数据结构,一般都会内置在很多高级语言中。由于Redis使用的是C语言并没有内置这种数据结构,所以Redis构建了自己的链表实现。 链表在Redis中应用广泛,比如列表建的底层实现之一就是链表。当一个列表键包含了数量比较多…

Python字符串类型

目录 目标 版本 官方文档 书写格式 字符串合并 常用函数 字母转小写(首字母转大写) 字母转小写(适用于在国际化环境中,忽略字母大小写进行比较的场景) 字母转小写(适用于非国际化环境中&#xff0…

JSON 格式的接口测试流程【Eolink Apikit】

在进行JSON格式的接口测试时,需要使用工具发送HTTP请求并获取响应。测试工具可以是单独的测试框架,如 Eolink Apikit。测试人员需要根据接口文档和测试用例编写测试脚本,然后运行测试并分析结果,以确保接口的质量和稳定性。 当我…

数据库mysql详细教学

1024 byte 构成 1 kb 1024 KB > 1MB 1024 MB > 1GB 1024 GB > 1TB 1024 TB > 1PB 内存的数据,断电后会丢失。外存的数据,断电后数据还在~ “持久化” 这样的次,意思就是把数据写到硬盘上。 mysql的第一组基本操作:数…

02_SHELL编程之流程控制和循环语句

课程目标 熟悉流程控制语句基本语法,如if…else… 掌握for循环语句的基本语法结构 掌握while和until循环语句的基本语法结构 ###一、流程控制语句 ####1. 基本语法结构 F: false 假 T: true 真 if [ condition ];thencommandcommand fi ​ [ 条件 ] &&a…

吴恩达《机器学习》8-7:多元分类

在机器学习领域,经常会遇到不止两个类别的分类问题。这时,需要使用多类分类技术。本文将深入探讨多类分类,并结合学习内容中的示例,了解神经网络在解决这类问题时的应用。 一、理解多类分类 多类分类问题是指当目标有多个类别时…

获取微信小程序二维码

可直接通过微信扫描小程序二维码直接进入小程序,可用在分享推广业务。 目录 Curl请求方法 获取小程序token 获取小程序二维码 参数说明 注意 请求结果 Curl请求方法 需要请求微信小程序的API接口,封装好curl请求方法。 代码如下: /*…

LSB隐写+十六进制转字符串

这张图片同样使用的是LSB隐写(即最不显著位隐写) 但是这道题目使用一个小技巧,将flag用十六进制的形式加了一层伪装 LSB隐写 通过StegSolve打开该图片,之后选择Analyse-》data extract来分析图片的LSB隐写 首先先点击选择LSB …

MIB 6.1810实验Xv6 and Unix utilities(3)pingpong

Mit6.S081-实验1-Xv6 and Unix utilities-pingpong问题_Isana_Yashiro的博客-CSDN博客 Write a user-level program that uses xv6 system calls to ping-pong a byte between two processes over a pair of pipes, one for each direction. The parent should send a byte to…

【精选】JavaScript语法大合集【附代码和超详细介绍以及使用】

JavaScript语法大合集 JavaScript引入到文件 嵌入到HTML文件中 <body><script>var num10;console.log(num);</script> </body>引入本地独立JS文件 <body><script src"./hello.js"></script> </body>引入网络来源…

nodejs spawn

Node.js 的子进程 (child_process) 模块下有一 spawn 函数&#xff0c;可以用于调用系统上的命令&#xff0c;如在 Linux, macOS 等系统上&#xff0c;我们可以执行如下代码来调用通用的 npm 命令。 const spawn require(child_process).spawn; spawn(npm, {stdio: inherit …

利用JavaScript实现ISO周日历[]

基础知识 阳历&#xff1a; 就是以太阳来计算日期的一类历法&#xff1b;阴历&#xff1a; 就是以月亮来计算日期的一类历法&#xff1b;公历&#xff1a; 属阳历的一种&#xff0c;我国现在使用的就是公历&#xff1b;农历&#xff1a; 我国的农历是一种阴阳合历&#xff0c;…

eclipse启动无法找到类(自定义监听器)

一.报错 二.排查 1.首先检查代码是否有问题 本人报错是找不到监听器&#xff0c;故检查监听器的代码和web.xml文件是否有问题 public class DoorListener implements ServletContextListener 监听器是否继承并实现ServletContextListener中的方法。 web.xml中&#xff1a; &…

linux 服务器进程、端口查找,nginx 配置日志查找,lsof 命令详解

一 、根据端口号 查看文件的部署位置 1.1 使用查看端口号对应的进程信息 方式一 &#xff1a; 使用netstat命令 netstat -tuln | grep 端口号-t&#xff1a;显示TCP连接 -u&#xff1a;显示UDP连接 -l&#xff1a;仅显示监听状态的连接 -n&#xff1a;以数字形式显示端口…

【EI会议征稿】第四届机械设计与仿真国际学术会议(MDS 2024)

【高录用快检索】第四届机械设计与仿真国际学术会议&#xff08;MDS 2024) 2024 4th International Conference on Mechanical Design and Simulation 2024年第四届机械设计与仿真国际学术会议&#xff08;MDS 2024) 将于2024年03月01-03日在中国西安召开。MDS 2024将围绕“…

面试必考精华版Leetcode2542. 最大子序列的分数

题目&#xff1a; 代码&#xff08;首刷看解析 2023年11月17日&#xff09;&#xff1a; class Solution { public:long long maxScore(vector<int>& nums1, vector<int>& nums2, int k) {int n nums1.size();typedef pair<int,int> pii;// int有序…