当前位置:首页 > 科技  > 软件

Java 21 的虚拟线程:高性能并发应用的福音

来源: 责编: 时间:2023-12-08 09:14:12 172观看
导读Java 21 最重要的特性之一就是虚拟线程 (JEP 444)。这些轻量级的线程降低了编写、维护和观察高吞吐量并行应用所需的努力。在讨论新特性之前,让我们先看一下当前的状态,以便更好地理解它试图解决什么问题以及带来了哪些

Java 21 最重要的特性之一就是虚拟线程 (JEP 444)。这些轻量级的线程降低了编写、维护和观察高吞吐量并行应用所需的努力。xzw28资讯网——每日最新资讯28at.com

在讨论新特性之前,让我们先看一下当前的状态,以便更好地理解它试图解决什么问题以及带来了哪些好处。xzw28资讯网——每日最新资讯28at.com

平台线程

在引入虚拟线程之前,我们习惯使用的线程是 java.lang.Thread,它背后是所谓的平台线程 (platform threads)。xzw28资讯网——每日最新资讯28at.com

这些线程通常与操作系统调度的内核线程一一映射。操作系统线程相当“重”,这使得它们适合执行所有类型的任务。xzw28资讯网——每日最新资讯28at.com

根据操作系统和配置,它们默认情况下会消耗大约2到10 MB的内存。因此,如果你想在高负载并发应用程序中使用一百万个线程,最好要有超过2 TB的可用内存!xzw28资讯网——每日最新资讯28at.com

这存在一个明显的瓶颈,限制了我们实际可以在没有缺点的情况下拥有的线程数量。xzw28资讯网——每日最新资讯28at.com

每个请求一个线程

这很成问题,因为它直接与典型的服务器应用程序“每个请求一个线程”的方法相冲突。使用每个请求一个线程有很多优点,例如更简单的状态管理和清理。但它也创造了可扩展性限制。应用程序的“并发单位”,在这种情况下是一个请求,需要一个“平台并发单位”。因此,线程很容易被原始CPU能力或网络耗尽。xzw28资讯网——每日最新资讯28at.com

即使“每个请求一个线程”有许多优点,共享重量级的线程可以更均匀地利用硬件,但也需要一种完全不同的方法。xzw28资讯网——每日最新资讯28at.com

异步救援

而不是在单个线程上运行整个请求,它的每个部分都从池中使用一个线程,当它们的任务完成时,另一个任务可能会重用同一个线程。这允许代码需要更少的线程,但引入了异步编程的负担。xzw28资讯网——每日最新资讯28at.com

异步编程伴随着它自己的范例,具有一定的学习曲线,并且可能会使程序更难理解和跟踪。请求的每个部分可能都在不同的线程上执行,从而创建没有合理上下文的堆栈跟踪,并使调试某些内容变得非常棘手甚至几乎不可能。xzw28资讯网——每日最新资讯28at.com

Java有一个用于异步编程的优秀API,CompletableFuture。但这是一个复杂的API,并且不太适合许多Java开发人员习惯的思维方式。xzw28资讯网——每日最新资讯28at.com

重新审视“每个请求一个线程”模型,很明显,一种更轻量级的线程方法可以解决瓶颈并提供一种熟悉的做事方式。xzw28资讯网——每日最新资讯28at.com

轻量级线程

由于平台线程的数量是无法在没有更多硬件的情况下改变的,因此需要另一个抽象层,切断可怕的 1:1 映射,它是首先造成瓶颈的原因。xzw28资讯网——每日最新资讯28at.com

轻量级线程不与特定的平台线程绑定,也不会伴随大量的预分配内存。它们由运行时而不是底层操作系统调度和管理。这就是为什么可以创建大量轻量级线程的原因。xzw28资讯网——每日最新资讯28at.com

这个概念并不新鲜,许多语言都采用某种形式的轻量级线程:xzw28资讯网——每日最新资讯28at.com

  • Go 语言中的 Goroutine
  • Erlang 进程
  • Haskell 线程
  • 等等

Java最终于第21版中引入了自己的轻量级线程实现:虚拟线程 (Virtual Threads)。xzw28资讯网——每日最新资讯28at.com

虚拟线程

虚拟线程是一种新的轻量级java.lang.Thread变体,是Project Loom的一部分,它不是由操作系统管理或调度的。相反,JVM负责调度。xzw28资讯网——每日最新资讯28at.com

当然,任何实际的工作都必须在平台线程中运行,但是JVM使用所谓的“载体线程”(carrier threads) 来“携带”任何虚拟线程,以便在它们需要执行时执行这些线程。xzw28资讯网——每日最新资讯28at.com

图片图片xzw28资讯网——每日最新资讯28at.com

JVM/操作系统线程调度器xzw28资讯网——每日最新资讯28at.com

所需的平台线程在一个 FIFO 工作窃取 ForkJoinPool 中进行管理,该池默认情况下使用所有可用的处理器,但可以通过调整系统属性jdk.virtualThreadScheduler.parallelism来根据需求进行修改。xzw28资讯网——每日最新资讯28at.com

ForkJoinPool与其他功能(例如并行流)使用的通用池之间的主要区别在于,通用池以LIFO模式运行。xzw28资讯网——每日最新资讯28at.com

廉价且丰富的线程

拥有廉价且轻量级的线程,可以使用“每个请求一个线程”模型,而不必担心实际需要多少个线程。如果你的代码在虚拟线程中调用阻塞 I/O 操作,则运行时会挂起虚拟线程,直到它可以稍后恢复。xzw28资讯网——每日最新资讯28at.com

这样,硬件就可以被优化到几乎最佳的水平,从而实现高水平的并发性,因此也实现高吞吐量。xzw28资讯网——每日最新资讯28at.com

因为它们非常廉价,所以虚拟线程不会被重用或需要池化。每个任务都由其自己的虚拟线程表示。xzw28资讯网——每日最新资讯28at.com

设置边界

调度器负责管理载体线程,因此需要一定的边界和分离,以确保可能的“无数”虚拟线程按照预期运行。这是通过在载体线程及其可能携带的任何虚拟线程之间不保持线程关联来实现的:xzw28资讯网——每日最新资讯28at.com

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

让我们看看代码

使用Virtual Threads最大的好处是,你不需要学习新的范例或复杂的API,就像使用异步编程一样。相反,你可以像对待非虚拟线程一样处理它们。xzw28资讯网——每日最新资讯28at.com

创建平台线程

创建平台线程很简单,就像使用 Runnable 创建一样:xzw28资讯网——每日最新资讯28at.com

Runnable fn = () -> {    // your code here};Thread thread = new Thread(fn).start();

随着Project Loom简化了新的并发方法,它还提供了一种创建平台支持线程的新方法:xzw28资讯网——每日最新资讯28at.com

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

实际上,现在还有一个完整的fluent API,因为ofPlatform()会返回一个Thread.Builder.OfPlatform实例:xzw28资讯网——每日最新资讯28at.com

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

但你肯定不是来学习创建“旧”线程的新方法的,我们想要一点新的东西。继续看。xzw28资讯网——每日最新资讯28at.com

创建虚拟线程

对于虚拟线程,也有类似的fluent API:xzw28资讯网——每日最新资讯28at.com

Runnable fn = () -> {  // your code here};Thread thread = Thread.ofVirtual(fn)                      .start();

除了构建器方法之外,你还可以直接使用以下方式执行Runnable:xzw28资讯网——每日最新资讯28at.com

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

由于所有虚拟线程始终是守护线程,因此如果你想在主线程上等待,请不要忘记调用join()。xzw28资讯网——每日最新资讯28at.com

创建虚拟线程的另一种方法是使用 Executor:xzw28资讯网——每日最新资讯28at.com

var executorService = Executors.newVirtualThreadPerTaskExecutor();executorService.submit(() -> {  // your code here});

小结

尽管Scoped Values (JEP 446) 和Structured Concurrency (JEP 453) 仍然是Java 21中的预览功能,但Virtual Threads已经成为一个成熟的、适用于生产环境的功能。xzw28资讯网——每日最新资讯28at.com

它们是Java并发的一种通用且强大的新方法,将对我们未来的程序产生重大影响。它们使用了熟悉的和可靠的“每个请求一个线程”方法,同时以最优化的方式利用所有可用硬件,而不需要学习新的范例或复杂的API。xzw28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-39505-0.htmlJava 21 的虚拟线程:高性能并发应用的福音

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 你 UTF-8 乱码,关我 Unicode 什么事

下一篇: 一款小而美的开源滑动验证码组件

标签:
  • 热门焦点
  • 卢伟冰长文解析K60至尊版 对Redmi有着里程碑式的意义

    卢伟冰长文解析K60至尊版 对Redmi有着里程碑式的意义

    在今天的Redmi后性能时代战略发布会结束之后,Redmi总经理卢伟冰又带来了一篇长文,详解了为什么 Redmi 要开启后性能时代?为什么选择和 MediaTek、Pixelworks 深度合作?以及后性
  • 小米官宣:2023年上半年出货量中国第一!

    小米官宣:2023年上半年出货量中国第一!

    今日早间,小米电视官方微博带来消息,称2023年小米电视上半年出货量达到了中国第一,同时还表示小米电视的巨屏风暴即将开始。“公布一个好消息2023年#小米电视上半年出货量中国
  • 直屏旗舰来了 iQOO 12和K70 Pro同台竞技

    直屏旗舰来了 iQOO 12和K70 Pro同台竞技

    旗舰机基本上使用的都是双曲面屏幕,这就让很多喜欢直屏的爱好者在苦等一款直屏旗舰,这次,你们等到了。据博主数码闲聊站带来的最新爆料称,Redmi下代旗舰K70 Pro和iQOO 12两款手
  • 如何通过Python线程池实现异步编程?

    如何通过Python线程池实现异步编程?

    线程池的概念和基本原理线程池是一种并发处理机制,它可以在程序启动时创建一组线程,并将它们置于等待任务的状态。当任务到达时,线程池中的某个线程会被唤醒并执行任务,执行完任
  • 网红炒股不为了赚钱,那就是耍流氓!

    网红炒股不为了赚钱,那就是耍流氓!

    来源:首席商业评论6月26日高调宣布入市,网络名嘴大v胡锡进居然进军了股市。在一次财经媒体峰会上,几个财经圈媒体大佬就“胡锡进炒股是否知道认真报道”展开讨论。有
  • 国行版三星Galaxy Z Fold5/Z Flip5发布 售价7499元起

    国行版三星Galaxy Z Fold5/Z Flip5发布 售价7499元起

    2023年8月3日,三星电子举行Galaxy新品中国发布会,正式在国内推出了新一代折叠屏智能手机三星Galaxy Z Fold5与Galaxy Z Flip5,以及三星Galaxy Tab S9
  • 三星获批量产iPhone 15全系屏幕:苹果史上最惊艳直屏

    三星获批量产iPhone 15全系屏幕:苹果史上最惊艳直屏

    按照惯例,苹果将继续在今年9月举办一年一度的秋季新品发布会,有传言称发布会将于9月12日举行,届时全新的iPhone 15系列将正式与大家见面,不出意外的话
  • 微软发布Windows 11新版 引入全新任务栏状态

    微软发布Windows 11新版 引入全新任务栏状态

    近日,微软发布了Windows 11新版,而Build 22563更新主要引入了几周前曝光的平板模式任务栏等,系统更流畅了。更新中,Windows 11加入了专门针对平板优化的任务栏
  • 2022爆款:ROG魔霸6 冰川散热系统持续护航

    2022爆款:ROG魔霸6 冰川散热系统持续护航

    喜逢开学季,各大商家开始推出自己的新产品,进行打折促销活动。对于忠实的端游爱好者来说,能够拥有一款梦寐以求的笔记本电脑是一件十分开心的事。但是现在的
Top