首页 > 其他分享 >jdk21-虚拟线程

jdk21-虚拟线程

时间:2023-11-29 22:56:12浏览次数:40  
标签:jdk21 Java 操作系统 虚拟 线程 堆栈 请求

jdk文档:https://openjdk.org/jeps/444

关键内容整理

  虚拟线程是轻量级线程,可显著减少编写、维护和观察高吞吐量并发应用程序的工作量。

  默认情况下,直接使用 API 创建的虚拟线程(而不是通过 创建的虚拟线程)现在也会在其整个生命周期内受到监视,并且可以通过观察虚拟线程部分中描述的新线程转储进行观察。Thread.BuilderExecutors.newVirtualThreadPerTaskExecutor().

  对于给定的请求处理持续时间(即延迟),应用程序同时处理的请求数(即并发)必须与到达速率(即吞吐量)成比例增长。例如,假设平均延迟为 50 毫秒的应用程序通过并发处理 200 个请求,实现了每秒 10 个请求的吞吐量。为了使该应用程序扩展到每秒 2000 个请求的吞吐量,它需要同时处理 100 个请求。如果每个请求在请求的持续时间内在线程中处理,则要使应用程序跟上,线程数必须随着吞吐量的增长而增长。

  • 可用线程的数量是有限的,因为 JDK 将线程实现为操作系统 (OS) 线程的包装器。操作系统线程的成本很高,因此我们不能有太多的线程。
  • 如果每个请求在其持续时间内消耗一个线程,从而消耗一个操作系统线程,那么线程数通常会在其他资源(如 CPU 或网络连接)耗尽之前很久就成为限制因素。
  • JDK 当前的线程实现将应用程序的吞吐量限制在远低于硬件可以支持的水平。即使线程被池化,也会发生这种情况,因为池化有助于避免启动新线程的高成本,但不会增加线程总数。

  Java 运行时可以以一种映射Java 线程与操作系统线程的一对一对应关系的方式实现 Java 线程。

  正如操作系统通过将大型虚拟地址空间映射到有限数量的物理 RAM 来产生大量内存的错觉一样,Java 运行时通过将大量虚拟线程映射到少量的操作系统线程,可以给人一种大量线程的错觉。

  “每个请求线程”样式的应用程序代码可以在请求的整个持续时间内在虚拟线程中运行,但虚拟线程仅在 CPU 上执行计算时才使用操作系统线程。

  • 当在虚拟线程中运行的代码调用 API 中的阻塞 I/O 操作时,运行时将执行非阻塞 OS 调用,并自动挂起虚拟线程,直到以后可以恢复。
  • 虚拟线程只是创建成本低廉且几乎无限丰富的线程。硬件利用率接近最佳,允许高级别的并发性,从而实现高吞吐量,同时应用程序与 Java 平台及其工具的多线程设计保持和谐。
  • 大多数虚拟线程的生存期很短,并且具有浅层调用堆栈,执行的操作仅为单个 HTTP 客户端调用或单个 JDBC 查询。相比之下,平台线程重量大且价格昂贵,因此通常必须合并。它们往往生存期长,具有深厚的调用堆栈,并在许多任务之间共享。

  现在,JDK 中每个 java.lang.Thread 实例都是一个平台线程。平台线程在底层操作系统线程上运行 Java 代码,并在代码的整个生命周期内捕获操作系统线程。平台线程数限制为操作系统线程数。

  虚拟线程是在底层操作系统线程上运行 Java 代码,但在代码的整个生命周期内不捕获操作系统线程的实例。这意味着许多虚拟线程可以在同一操作系统线程上运行其 Java 代码,从而有效地共享它。虽然平台线程垄断了宝贵的操作系统线程,但虚拟线程却不会。虚拟线程数可以远大于操作系统线程数。java.lang.Thread

  虚拟线程是由 JDK 而不是 OS 提供的线程的轻量级实现。

  开发人员可以选择是使用虚拟线程还是平台线程。下面是一个创建大量虚拟线程的示例程序。程序首先获取一个 ExecutorService,它将为每个提交的任务创建一个新的虚拟线程。然后,它提交 10,000 个任务并等待所有任务完成:

try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 10_000).forEach(i -> {
        executor.submit(() -> {
            Thread.sleep(Duration.ofSeconds(1));
            return i;
        });
    });
}  // executor.close() is called implicitly, and waits

虚拟线程可以在以下情况下显著提高应用程序吞吐量

  • 并发任务数很高(超过几千个),并且
  • 工作负载不受 CPU 限制,因为在这种情况下,线程数比处理器内核多得多,无法提高吞吐量。

  虚拟线程有助于提高典型服务器应用程序的吞吐量,因为此类应用程序由大量并发任务组成,这些任务花费大量时间等待。

  虚拟线程支持线程局部变量和线程中断,就像平台线程一样。

  开发人员通常会将应用程序代码从传统的基于线程池的 .线程池与任何资源池一样,旨在共享昂贵的资源,但虚拟线程并不昂贵,因此永远不需要将它们池化。

  开发人员有时会使用线程池来限制对有限资源的并发访问。例如,如果一个服务无法处理超过 20 个并发请求,则通过提交到大小为 20 的线程池的任务向服务发出所有请求将确保这一点。这个成语已经变得无处不在,因为平台线程的高成本使线程池无处不在,但不要为了限制并发而试图池化虚拟线程。相反,请使用专门为此目的设计的构造,例如信号量。

  结合线程池,开发人员有时会使用线程局部变量在共享同一线程的多个任务之间共享昂贵的资源。例如,如果数据库连接的创建成本很高,则可以打开它一次,并将其存储在线程局部变量中,供同一线程中的其他任务稍后使用。如果将代码从使用线程池迁移到每个任务使用虚拟线程,请警惕此习惯用法,因为为每个虚拟线程创建昂贵的资源可能会显著降低性能。更改此类代码以使用替代缓存策略,以便在大量虚拟线程之间有效地共享昂贵的资源。

在两种情况下,虚拟线程在阻塞操作期间无法卸载,因为它被固定到其载体:

  1. 当它在块或方法中执行代码时,或者synchronized
  2. 当它执行方法或外函数时。native

  虚拟线程堆栈作为堆栈块对象存储在 Java 的垃圾回收堆中。堆栈会随着应用程序的运行而增长和收缩,既可以节省内存,也可以容纳深度堆栈,最高可达 JVM 配置的平台线程堆栈大小。这种效率使大量虚拟线程成为可能,从而使服务器应用程序中每个请求线程样式的持续可行性成为可能。

  一般来说,虚拟线程所需的堆空间量和垃圾回收器活动量很难与异步代码进行比较。一百万个虚拟线程至少需要一百万个对象,但共享平台线程池的一百万个任务也是如此。此外,处理请求的应用程序代码通常会跨 I/O 操作维护数据。每个请求线程代码可以将该数据保存在局部变量中,这些变量存储在堆中的虚拟线程堆栈中,而异步代码必须将相同的数据保存在从管道的一个阶段传递到下一个阶段的堆对象中。一方面,虚拟线程所需的堆栈帧布局比紧凑对象更浪费;另一方面,虚拟线程可以在许多情况下(取决于低级 GC 交互)更改和重用其堆栈,而异步管道始终需要分配新对象,因此虚拟线程可能需要较少的分配。总体而言,每个请求线程与异步代码的堆消耗和垃圾回收器活动应该大致相似。随着时间的流逝,我们希望使虚拟线程堆栈的内部表示更加紧凑。

  与平台线程堆栈不同,虚拟线程堆栈不是 GC 根。因此,它们包含的引用不会被执行并发堆扫描的垃圾回收器(如 G1)在停止世界暂停时遍历

标签:jdk21,Java,操作系统,虚拟,线程,堆栈,请求
From: https://www.cnblogs.com/use-D/p/17861868.html

相关文章

  • CPU虚拟化的过程
    VMCS是VirtualMachineControlStructure。是Intel实现CPU虚拟化,记录vCPU状态的一个关键数据结构。VMCS数据结构主要包含以下信息。Guest-statearea,即vCPU的状态信息,包括vCPU的基本运行环境,例如寄存器等。Host-statearea,是物理CPU的状态信息。物理CPU和vCPU之......
  • 主线程如何获取子线程异常
    主线程如何获取子线程异常常规情况:一般我们没有办法通过主线程去获取子线程的异常举个例子:publicclasstest11_29{publicstaticvoidmain(String[]args){try{Threadthread=newThread(newmyExceptionRunner());thread.star......
  • 解决主机与虚拟机之间无法复制粘贴的问题办法
    1.卸载VMwareToolssudoapt-getautoremoveopen-vm-tools2.联网安装VMwaretoolssudoapt-getinstallopen-vm-tools-desktop3.记得要重启虚拟机!ps:重启后,使用ctrlc+v似乎还是不能复制粘贴,也不能通过拖动文件来复制,但是可以通过鼠标右键复制粘贴文本或者文件,也算解......
  • 虚拟机进行实验八遇到的坑(一)
    idea依赖下载报错//引入阿里云镜像下载就ok啦~~~<repositories><repository><id>alimaven</id><name>aliyunmaven</name><url>https://maven.aliyun.com/nexus/content/groups/public/</url......
  • VMWARE虚拟机的CPU分配(VMWARE14):处理器数量、核心数量分配验证
    最近搞了个12核24线程的服务器CPU,加上华南金牌的主板,配了64G的内存,有点飘。然后用VMWARE14建了好几个虚拟机,多开耍耍。然后CPU的分配成了一个问题,因此上网查了下,有两种说法:方案1:有说虚拟机处理器设置页面的“处理器数量”指的是“核心数”,“每个处理器的内核数量”是超线程数量。......
  • 解锁AIGC大模型,打造你的专属虚拟女友
    什么是AIGC大模型?AIGC大模型是一种基于人工智能技术的生成式模型,它可以根据用户的输入和偏好,生成具有高度真实感和个性化的虚拟人物。这些虚拟人物不仅拥有独特的外貌、声音和性格,还可以与用户进行智能互动,为用户提供陪伴、娱乐和情感支持。如何打造专属虚拟女友?想要打造一位专......
  • 微信小程序车牌号码虚拟键盘
    WXML<viewclass="page"><!--车牌号码输入框--><viewclass="carNumber"><viewclass="weui-cells__title">请输入您要缴费的车牌号码</view><!--车牌号头两位--><viewclass="carNumber-items&......
  • 发烧平台完全是AMD的天下!32核心线程撕裂者者7970X评测:内容创作性价比之选
    一、前言:32核心的线程撕裂者7970X11月20日,AMD正式发布了Zen4架构的线程撕裂者处理器,成为了无可争议的最强处理器,我们快科技也同步带来了HEDT发烧平台旗舰型号,64核心128线程线程撕裂者7980X的首发评测。除了线程撕裂者7980X之外,AMD同时还发布了32核心的线程撕裂者7970X、24核心......
  • 华三虚拟化系统安装
    正常启动后截图 进行分区(比较懒直接自动。手动方法和正常做Linux系统操作一样) 发现报错(附带翻译)    一般出现这个问题,都是因为服务器中已经存在了系统,如果不需要就直接全部删掉继续往下安装 和做Linux系统的操作差不多就不叙述了,看图     ......
  • 命令行界面的虚拟机如何转成图形界面
    教程相关步骤1、查看有什么可以安装yumgrouplist2、安装GUI图形界面yumgroupinstall-y"ServerwithGUI""DevelopmentTools"3、打开下载好的GUI图形界面startx开启成功!......