Java 21新特性-虚拟线程 审核中

这篇具有很好参考价值的文章主要介绍了Java 21新特性-虚拟线程 审核中。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文翻译自国外论坛 medium,原文地址:https://medium.com/@benweidig/looking-at-java-21-virtual-threads-0ddda4ac1be1

Java 21 版本更新中最重要的功能之一就是虚拟线程 (JEP 444)。这些轻量级线程减少了编写、维护和观察高吞吐量并发应用程序所需的工作量。

正如我的许多其他文章一样,在推出新功能之前,让我们先看看 Java 21 版本更新前的现状,以便更好地了解 Java 21 版本试图解决的问题以及好处是什么。

平台线程

在引入虚拟线程之前,java.lang.Thread 包已经支持所谓的平台线程。

这些线程通常以 1:1 的方式映射到操作系统调度的内核线程。操作系统线程相当“重”。这使得它们可以执行所有类型的任务。

根据操作系统和 JVM 启动参数配置的不同,一个平台线程默认消耗 1 MB 的空间。因此如果我们想在重负载高并发应用程序中使用一百万个线程,我们最好有超过 1 TB 的空闲内存!

如上所述,平台线程有一个明显的内存瓶颈限制了我们实际上可以拥有的线程数量。

每个请求一个线程

每个请求使用单个线程有很多优点,例如更容易的状态管理和清理。但它也造成了可扩展性限制。应用程序的“并发单元”(在本例中为请求)需要单个“并发平台单元”(在本例中也就是平台线程),但是在重负载高并发应用程序中,平台线程容易因为内存不足、CPU 资源耗尽而创建失败。

尽管“每个请求一个线程”有很多优点,平台线程可以更均匀地利用硬件,但我们还是需要一种完全不同的方法。

使用线程池

与在单个线程上处理以个请求不同,当任务完成时,线程会被线程池回收,因此另一个请求可能会重用相同的线程。这允许我们的程序使用更少的线程处理更多的请求,但会带来异步编程的负担。

异步编程具有自己的范例,具有一定的学习曲线,并且可能使我们的程序更难以理解和遵循。请求的每个部分可能在不同的线程上执行,在没有合理上下文的情况下创建堆栈跟踪,并使调试变得非常棘手甚至几乎不可能。

重新审视“每个请求一个线程”模型,很明显,我们需要一种更轻量级的线程方法来解决这个瓶颈,并最好按照我们熟悉的方式。

轻量级线程

由于平台线程的数量在不新增硬件资源的情况下无法改变,因此也就需要另一层抽象,以切断首先产生瓶颈的可怕的 1:1 映射。

轻量级线程不依赖于特定的平台线程,也不会为其分配大量内存。它们由运行时的 JVM 调度和管理而不是底层操作系统。这就是为什么可以创建大量轻量级线程的原因。

轻量级线程的概念并不新鲜,许多语言都有某种形式的轻量级线程:

  • Go 语言中的 Goroutines(协程)
  • Erlang 语言中的 Processes(轻量级进程)
  • Haskell Threads

Java 也在 21 版本中引入了自己的轻量级线程实现:虚拟线程

虚拟线程

虚拟线程是一个新的轻量级 java.lang.Thread 变体,是 Project Loom 项目的一部分,不由操作系统管理或调度。相反由 JVM 负责调度。当然在实际工作反映到操作系统还是以平台线程运行,但 JVM 正是利用所谓的载体线程(即平台线程)来“承载”虚拟线程,以便在需要时执行。

所需的平台线程以 FIFO 工作方式在 ForkJoinPool 中进行管理,默认情况下,它使用所有可用的处理器,但可以通过调整系统属性 jdk.virtualThreadScheduler.parallelism 来根据我们的要求进行修改。我们熟悉的 ForkJoinPool 与并行流等其他功能使用的公共池之间的主要区别在于,公共池以 LIFO 模式运行。

物美价廉

虚拟线程是廉价且轻量级的,我们可以使用“每个请求一个线程”模型,而不必担心实际需要多少个线程。如果我们的代码在虚拟线程中调用阻塞 I/O 操作,则运行时会挂起这个被阻塞的虚拟线程,直到挂起结束后就可以恢复。这样一来,程序对硬件的利用就可以达到近乎最佳并提供高水平的并发性,从而实现高吞吐量。

因为虚拟线程非常便宜,所以虚拟线程不会被重用或需要被池化。每个任务都由其自己的虚拟线程来执行。

设定界限

JVM 调度程序通过载体线程来管理虚拟线程,因此需要一定的边界和分隔来确保可能的“无数”虚拟线程按预期运行。这是通过在载体线程和它可能承载的任何虚拟线程之间保持无线程关联来实现的:

  • 虚拟线程无法访问载体线程,Thread.currentThread() 返回虚拟线程本身。
  • 堆栈跟踪是独立的,虚拟线程中抛出的任何异常仅包含其自己的堆栈帧。
  • 虚拟线程的线程局部变量对其载体线程不可用,反之亦然。
  • 从代码的角度来看,载体线程及其虚拟线程对平台线程的共享是不可见的。

代码展示

在我看来,虚拟线程最好的事情之一就是我们不需要学习新的编程范例或复杂的新 API,就能够完成异步编程。在使用上,我们可以像对待平台线程一样对待虚拟线程。

创建平台线程

创建平台线程很简单,就像使用 Runnable 创建一样:

Runnable fn = () -> {
  // your code here
};

Thread thread = new Thread(fn).start();

随着 Project Loom 项目简化了新的并发方法,还提供了一种创建平台线程的新方法:

Thread thread = Thread.ofPlatform().
                      .start(runnable);

实际上,现在有一个完整的 Fluent API,因为 ofPlatform() 返回一个 Thread.Builder.OfPlatform 实例:

Thread thread = Thread.ofPlatform().
                      .daemon()
                      .name("my-custom-thread")
                      .unstarted(runnable);

但你来这里显然不是为了学习创建“旧”线程的新方法,你想要新的东西!

创建虚拟线程

对于虚拟线程,同样有一个 Fluent API:

Runnable fn = () -> {
  // your code here
};

Thread thread = Thread.ofVirtual(fn)
                      .start();

除了构建器方法之外,我们还可以直接使用以下命令创建虚拟线程:

Thread thread = Thread.startVirtualThread(() -> {
  // your code here
});

由于所有虚拟线程始终都是守护线程,因此如果我们想在主线程上等待虚拟线程执行完毕,可以调用 join() 方法。

创建虚拟线程的另一种方法是使用 Executor 类:

var executorService = Executors.newVirtualThreadPerTaskExecutor();

executorService.submit(() -> {
  // your code here
});

总结

尽管作用域值 (JEP 446) 和结构化并发 (JEP 453) 仍然是 Java 21 中的预览功能,但虚拟线程已经成为可投入生产的成熟功能。

虚拟线程是一种通用且强大的 Java 并发新方式,将对我们的未来程序产生重大影响。虚拟线程使用熟悉且可靠的“每个请求一个线程”方法,同时以最佳方式利用所有可用硬件,无需学习新范例或复杂的 API。

关注公众号【waynblog】每周分享技术干货、开源项目、实战经验、国外优质文章翻译等,您的关注将是我的更新动力!文章来源地址https://www.toymoban.com/news/detail-711728.html

到了这里,关于Java 21新特性-虚拟线程 审核中的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java 21 虚拟线程:使用指南(一)

    虚拟线程是由 Java 21 版本中实现的一种轻量级线程。它由 JVM 进行创建以及管理。虚拟线程和传统线程(我们称之为平台线程)之间的主要区别在于,我们可以轻松地在一个 Java 程序中运行大量、甚至数百万个虚拟线程。 由于虚拟线程的数量众多,也就赋予了 Java 程序强大的

    2024年02月04日
    浏览(36)
  • Java21上手体验-分代ZGC和虚拟线程

    几天前Oracle刚刚发布了Java21, 由于这是最新的LTS版本,引起了大家的关注。 我也第一时间在个人项目中进行了升级体验。 一探究竟,和大家分享。 https://jdk.java.net/21/release-notes https://my.oschina.net/waylau/blog/10112170 JEP 431:序列集合 JEP 439:分代 ZGC JEP 440:记录模式 JEP 441:switc

    2024年02月08日
    浏览(29)
  • Java 21 正式 GA,虚拟线程真的来了

    UTC 时间 2023 年 9 月 19 日,期盼已久的 Java 21 终于发布正式版! 本文一起来看看其中最受 Java 开发者关注的一项新特性:Loom 项目的两个新特性之一的 ”虚拟线程(Virtual Thread)“(另外一个新特性是 ”结构化并发(Structured Concurrency)“,当前是预览状态),它被称之为 J

    2024年02月08日
    浏览(46)
  • Java 21 虚拟线程如何限流控制吞吐量

    虚拟线程(Virtual Threads)是 Java 21 所有新特性中最为吸引人的内容,它可以大大来简化和增强Java应用的并发性。但是,随着这些变化而来的是如何最好地管理此吞吐量的问题。本文,就让我们看一下开发人员在使用虚拟线程时,应该如何管理吞吐量。 在大多数情况下,开发

    2024年02月20日
    浏览(39)
  • Java21对虚拟线程进行http压测使用不同的GC

    JDK21默认GC是G1. JDK21除了G1外,还可以使用ZGC(Java11预览、Java15正式版),Java21在ZGC基础上继续推出了分代ZGC,目前还是试行阶段。 开启ZGC: java -XX:+UseZGC -jar myapp.jar 开启ZGC,并试用分代ZGC java -XX:+UseZGC -XX:+ZGenerational -jar myapp.jar 以下的对一个启用tomcat虚拟线程的spring boot 项目

    2024年02月05日
    浏览(43)
  • 【JDK21】详解虚拟线程

    目录 1.概述 2.虚拟线程是为了解决哪些问题 2.1.线程切换的巨大代价 2.2.哪些情况会造成线程的切换 2.3.线程资源是有限的 3.虚拟线程 4.适用场景 你发任你发,我用JAVA8?JDK21可能要对这句话say no了。 现在Oracle JDK是每4个版本,推出一个长期支持版本,JDK21就是前段时间发布的最

    2024年02月05日
    浏览(36)
  • jdk21 虚拟线程原理及使用分享

    jdk21已于北京时间9月19日21点正式发布, 其中引人注目的就是虚拟线程(Virtual Thread)随之正式发布, 不再是此前jdk19、jdk20中的预览版本。 平台线程 :java传统的线程是对系统线程的包装,为了区别于虚拟线程,因此将通过传统方式实现的线程叫做平台线程(Platform Thread) 虚拟线程

    2024年02月04日
    浏览(33)
  • JDK21最终版协程实现之虚拟线程

    JDK9 后的版本你觉得没必要折腾,我也认可,但是JDK21有必要关注。因为 JDK21 引入全新的并发编程模式。 一直沽名钓誉的GoLang吹得最厉害的就是协程了。JDK21 中就在这方面做了很大的改进,让Java并发编程变得更简单一点,更丝滑一点。 之前写过JDK21 Feature。 Virtual Threads 、

    2024年02月08日
    浏览(53)
  • 聊聊JDK19特性之虚拟线程

    在读《深入理解JVM虚拟机》这本书前两章的时候整理了JDK从1.0到最新版本发展史,其中记录了JDK这么多年来演进过程中的一些趣闻及引人注目的一些特性,在调研JDK19新增特性的时候了解到了虚拟线程这个概念,于是对虚拟线程进行学习整理内容如下。 虚拟线程(Virtual Thread

    2024年02月08日
    浏览(32)
  • JDK21中虚拟线程到底是什么?看完便知

    本文涉及到的技术:虚拟线程、结构化并发、线程池、TheadLocal,对原理感兴趣的可以直接跳到原理部分。 虚拟线程是JDK19中引入的,JDK21正式发布,我们先来看看虚拟线程的几种用法,然后再来分析底层实现原理。 先定义一个Runnable: 通过观察输出结果,就能知道当前运行

    2024年02月08日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包