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

一文搞懂为什么选择 Java 虚拟线程?

来源: 责编: 时间:2023-11-03 17:06:47 185观看
导读Hello folks,我是 Luga,今天我们来聊一下 Java 生态的核心技术—— Java Virtual Threads,即 “Java 虚拟线程” 。虚拟线程是 Java 中的一个重要创新,在 Project Loom 项目中开发的。自从 Java 19 开始作为预览功能引入,

Hello folks,我是 Luga,今天我们来聊一下 Java 生态的核心技术—— Java Virtual Threads,即 “Java 虚拟线程” 。RFs28资讯网——每日最新资讯28at.com

虚拟线程是 Java 中的一个重要创新,在 Project Loom 项目中开发的。自从 Java 19 开始作为预览功能引入,到 Java 21 以后成为正式版本(JEP 444),虚拟线程已经成为 JDK 的一部分。RFs28资讯网——每日最新资讯28at.com

一、为什么是 Java Virtual Threads ?

众所周知,JVM 是一个多线程环境,通过 java.lang.Thread 类型为我们提供了对操作系统线程的抽象。在 Project Loom 之前,JVM 中的每个线程都只是对操作系统线程的一种简单封装,我们可以称之为“平台线程”。RFs28资讯网——每日最新资讯28at.com

然而,所谓的“平台线程”,在某些特定的业务场景中,往往存在一些问题,从多个角度来看,它们都是昂贵的。首先,创建平台线程的成本很高。每当创建一个平台线程时,操作系统必须在堆栈中分配大量内存(以兆字节计)来存储线程的上下文、原生调用堆栈和 Java 调用堆栈。由于堆栈大小是固定的,这就导致了高昂的内存开销。此外,每当调度器对线程进行抢占式调度时,也需要移动大量的内存。RFs28资讯网——每日最新资讯28at.com

因此,我们可以想象,这在空间和时间上都是非常昂贵的操作。实际上,由于堆栈框架的巨大尺寸限制,我们对可创建的线程数量也存在限制。在 Java 中,我们很容易遇到 OutOfMemoryError,只需不断实例化新的平台线程,直到操作系统的内存耗尽为止。RFs28资讯网——每日最新资讯28at.com

private static void stackOverFlowErrorExample() {  for (int i = 0; i < 100_000; i++) {    new Thread(() -> {      try {        Thread.sleep(Duration.ofSeconds(1L));      } catch (InterruptedException e) {        throw new RuntimeException(e);      }    }).start();  }}

由于平台线程的创建成本较高,每个线程需要分配一定数量的堆栈内存,因此在某些情况下,如果我们不断实例化新的平台线程,直到操作系统的内存耗尽,就有可能迅速触发 OutOfMemoryError。RFs28资讯网——每日最新资讯28at.com

然而,这个过程的确切时间取决于多个因素,包括可用的内存大小、操作系统的线程限制以及 JVM 的配置。如果可用的内存较小,同时 JVM 的堆大小也较小,那么在不断实例化新的平台线程时,很可能会很快达到内存的极限,导致 OutOfMemoryError 的发生。RFs28资讯网——每日最新资讯28at.com

[0.949s][warning][os,thread] Failed to start thread "Unknown thread" - pthread_create failed (EAGAIN) for attributes: stacksize: 1024k, guardsize: 4k, detached.[0.949s][warning][os,thread] Failed to start the native thread for java.lang.Thread "Thread-4073"Exception in thread "main" java.lang.OutOfMemoryError: unable to create native thread: possibly out of memory or process/resource limits reached

上述示例展示了我们如何基于当前的受到限制的环境中进行并发编程。RFs28资讯网——每日最新资讯28at.com

然而,Java 自从问世以来一直致力于成为一种简单易用的编程语言。在并发编程领域,我们应该像编写顺序代码一样编写程序。事实上,在 Java 中,为每个并发任务创建一个新线程是编写并发程序更简单的方法之一。这种模型被称为"每个线程一个任务"。RFs28资讯网——每日最新资讯28at.com

接下来,我们来看一下虚拟线程内部架构,具体如下所示:RFs28资讯网——每日最新资讯28at.com

RFs28资讯网——每日最新资讯28at.com

使用这种方法,每个线程可以使用自己的局部变量来存储信息,从而大大减少了共享可变状态的需求。线程之间共享状态是并发编程中众所周知的"棘手部分"。然而,通过每个线程一个任务的模型,我们可以轻松地避免复杂的线程同步和共享状态的问题。RFs28资讯网——每日最新资讯28at.com

然而,正如之前提到的,使用这种方法也存在着限制,即我们能够创建的线程数量有限。由于平台线程的创建成本较高,每个线程都需要分配一定数量的堆栈内存,这限制了我们可以创建的线程数量。如果我们不加限制地创建大量线程,就有可能导致内存耗尽和性能下降。RFs28资讯网——每日最新资讯28at.com

需要注意的是,随着 Project Loom 的引入,虚拟线程的轻量级特性将显著改善线程创建成本和内存开销。这将使我们能够更轻松地创建大规模的并发任务,而不会受到线程数量限制的困扰。RFs28资讯网——每日最新资讯28at.com

二、如何创建 Virtual Threads ?

正如我们之前所提到的,虚拟线程是一种新型的线程,旨在解决平台线程的资源限制问题。它们是 java.lang.Thread 类型的替代实现,将堆帧(Heap Frame)存储在堆内存中,而不是堆栈中。RFs28资讯网——每日最新资讯28at.com

由于虚拟线程的堆栈存储在堆中,因此它们的初始内存占用非常小,通常只有几百字节,而不是兆字节。此外,堆栈块的大小可以动态调整。这意味着我们不需要为每个可能的用例分配数百兆字节的内存。RFs28资讯网——每日最新资讯28at.com

通常而言,创建一个新的虚拟线程非常简单。我们可以使用 java.lang.Thread类 型上的新工厂方法 ofVirtual 来实现。让我们首先定义一个实用函数,用于创建具有给定名称的虚拟线程的示例代码:RFs28资讯网——每日最新资讯28at.com

import java.lang.Thread;public class VirtualThreadExample {    public static void main(String[] args) {        Thread virtualThread = Thread.ofVirtual("VirtualThreadExample", VirtualThreadExample::runTask);        virtualThread.start();    }        public static void runTask() {        // 在虚拟线程中执行的任务代码        System.out.println("Running task in virtual thread");    }}

在上面的示例中,我们使用 Thread.ofVirtual 方法创建了一个名为 "VirtualThreadExample" 的虚拟线程,并指定了要在其中执行的任务代码。然后,我们调用 start 方法启动虚拟线程。RFs28资讯网——每日最新资讯28at.com

通过使用虚拟线程,我们可以更加灵活地管理线程的内存消耗,并提高并发程序的性能和可伸缩性。虚拟线程是 Project Loom 的关键特性之一,将极大地改善 Java 中的并发编程体验。RFs28资讯网——每日最新资讯28at.com

三、Virtual Threads 到底有哪些方面优势?

作为 Project Loom 提出的一种新的线程模型,即虚拟线程。虚拟线程是一种轻量级的线程,其堆栈存储在堆内存中,而不是在操作系统线程的堆栈中。这种设计使得虚拟线程的创建和销毁成本较低,并且可以创建大量的线程,而不会受到操作系统和硬件资源的限制。RFs28资讯网——每日最新资讯28at.com

虚拟线程的引入将改变 Java 中的并发编程方式。它们可以通过更高效地利用系统资源来提高并发性能,并且可以简化并发编程的复杂性。虚拟线程可以使用更少的内存,并且可以根据需求动态调整堆栈的大小,以提高资源利用率。RFs28资讯网——每日最新资讯28at.com

具体可参考如下所示:RFs28资讯网——每日最新资讯28at.com

1、减少应用程序内存消耗

与传统的由平台线程都映射到操作系统线程的生命周期相对比,虚拟线程通过较小的初始内存占用、动态调整堆栈大小、共享堆栈和更高效的内存管理等方式,减少了应用程序的内存消耗。这使得可以创建更多的线程,提高并发性能,并且更有效地利用系统资源。RFs28资讯网——每日最新资讯28at.com

2、提高应用程序吞吐量

在大多数架构中,应用程序可以处理的请求数量与应用程序服务器线程池中可用的线程数量成正比。因为每个客户请求都由单个唯一的线程处理。因此,如果可用的线程数量较少,则只能同时处理少量请求。这将降低应用程序的吞吐量。另一方面,如果应用程序服务器线程池配置了Java虚拟线程,它可以创建明显更高的线程数量(数百万),这将最终提高应用程序的吞吐量。RFs28资讯网——每日最新资讯28at.com

此外,在某些应用程序中,应用程序服务器线程池中的可用线程在其他计算资源(如CPU、内存、网络、存储)饱和之前首先饱和。对于这样的虚拟线程来说,这将是一个较大的增强。RFs28资讯网——每日最新资讯28at.com

3、减少无法创建新的本机线程的 “OutOfMemoryError” 异常

在 JVM 上运行的应用程序容易出现“java.lang.OutOfMemoryError:无法创建新的本机线程”。这种类型的内存错误通常发生在如下两种情况下:RFs28资讯网——每日最新资讯28at.com

(1)当应用程序创建的线程超过服务器(或容器)的 RAM 容量时RFs28资讯网——每日最新资讯28at.com

(2)当应用程序创建的线程超过操作系统允许的限制时(注:在操作系统中,有一个内核限制,该限制规定了单个进程可以创建的线程数量)。RFs28资讯网——每日最新资讯28at.com

通常而言,Java 虚拟线程在减少内存消耗方面具有显著优势。相比传统的平台线程,Java 虚拟线程通常更轻量级,它们占用的内存较少。这使得使用虚拟线程比使用平台线程更难达到 RAM 容量的饱和。RFs28资讯网——每日最新资讯28at.com

传统的平台线程需要分配操作系统线程,并且每个线程都有一定的内存开销。而虚拟线程在不做实际工作时,并不需要分配操作系统线程,因此虚拟线程应用程序超过操作系统线程限制的可能性要远远高于传统的平台线程。RFs28资讯网——每日最新资讯28at.com

虚拟线程的轻量级特性和更高的灵活性使得可以创建更多的线程,而不会受到操作系统和硬件资源的限制。这进一步增加了虚拟线程应用程序处理大规模并发的能力,提高了系统的可伸缩性。RFs28资讯网——每日最新资讯28at.com

4、提高应用程序可用性

在我们主流的系统架构中,应用程序通常需要与多个后端系统进行通信,如 API、数据库和第三方框架等。然而,当其中一个后端系统出现中断或响应缓慢时,传统的应用程序服务器线程会被阻塞,等待后端系统的响应。随着更多请求进入应用程序,越来越多的线程会被阻塞。在这种情况下,应用程序服务器线程池中的线程数量是有限的。如果所有线程都被阻塞等待后端系统的响应,那么就没有可用线程来处理新的请求,从而导致整个应用程序不可用。RFs28资讯网——每日最新资讯28at.com

然而,通过将应用程序服务器线程池配置为使用 Java 虚拟线程,可以解决上述问题并提高应用程序的可用性。使用虚拟线程,我们甚至可以轻松创建数百万个线程,而不会出现重大问题。当虚拟线程被阻塞等待后端系统的响应时,它会像任何其他应用程序对象一样,以非常轻量级的方式存储在 Java 堆区域中。因此,应用程序服务器线程池可以继续创建虚拟线程,而不会耗尽线程池中的线程资源,直到后端系统恢复。RFs28资讯网——每日最新资讯28at.com

这种优化策略为应用程序带来了巨大的潜力,提高了应用程序的可用性。即使在后端系统出现问题时,应用程序仍然能够继续创建和处理请求,而不会因为线程资源的耗尽而导致不可用状态。这种灵活性和弹性使得应用程序能够更好地应对高负载和故障情况,保持稳定的运行状态。RFs28资讯网——每日最新资讯28at.com

Java 虚拟线程提供了现代应用程序所需的强大且高效的并发模型。它简化了并发编程,并带来更好的资源利用率,因此有可能彻底改变开发人员在 Java 中处理并发代码的方式。RFs28资讯网——每日最新资讯28at.com

随着 Java 技术不断发展和创新,了解最新的功能如虚拟线程对于那些希望保持领先地位并充分利用 Java 生态系统潜力的开发人员来说至关重要。RFs28资讯网——每日最新资讯28at.com

虚拟线程提供了一种轻量级的线程模型,通过协作调度和高效的内存管理,大大减少了线程创建和管理的开销。这使得开发人员能够更容易地编写高性能、高并发的应用程序,而无需担心传统线程模型的限制和开销。RFs28资讯网——每日最新资讯28at.com

通过使用虚拟线程,开发人员可以更好地利用系统资源,提高应用程序的并发性能。虚拟线程的出现为 Java 生态系统带来了更多的潜力和机会,使得开发人员能够更好地应对现代应用程序中的并发需求。RFs28资讯网——每日最新资讯28at.com

因此,对于那些希望保持领先并充分利用 Java 生态系统的开发人员来说,了解虚拟线程等先进功能是至关重要的。这将使他们能够更好地应对并发编程挑战,并构建出高性能、可扩展的应用程序,从而在竞争激烈的软件开发市场中脱颖而出。RFs28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-16836-0.html一文搞懂为什么选择 Java 虚拟线程?

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

上一篇: 30 个基础而实用的 JavaScript 代码片段

下一篇: 聊聊分布式服务下的八种异步实现方式

标签:
  • 热门焦点
  • Mate60手机壳曝光 致敬自己的经典设计

    Mate60手机壳曝光 致敬自己的经典设计

    8月3日消息,今天下午博主数码闲聊站带来了华为Mate60的第三方手机壳图,可以让我们在真机发布之前看看这款华为全新旗舰的大致轮廓。从曝光的图片看,Mate 60背后摄像头面积依然
  • 容量越大越不坏?24万块硬盘故障率报告公布 这些产品零故障

    容量越大越不坏?24万块硬盘故障率报告公布 这些产品零故障

    8月5日消息,云存储服务商Backblaze发布了最新的硬盘故障率报告,年故障率有所上升。Backblaze发布的硬盘季度统计数据,其中包括故障率等重要方面。这些结
  • 十个可以手动编写的 JavaScript 数组 API

    十个可以手动编写的 JavaScript 数组 API

    JavaScript 中有很多API,使用得当,会很方便,省力不少。 你知道它的原理吗? 今天这篇文章,我们将对它们进行一次小总结。现在开始吧。1.forEach()forEach()用于遍历数组接收一参
  • 一文看懂为苹果Vision Pro开发应用程序

    一文看懂为苹果Vision Pro开发应用程序

    译者 | 布加迪审校 | 重楼苹果的Vision Pro是一款混合现实(MR)头戴设备。Vision Pro结合了虚拟现实(VR)和增强现实(AR)的沉浸感。其高分辨率显示屏、先进的传感器和强大的处理能力
  • 让我们一起聊聊文件的操作

    让我们一起聊聊文件的操作

    文件【1】文件是什么?文件是保存数据的地方,是数据源的一种,比如大家经常使用的word文档、txt文件、excel文件、jpg文件...都是文件。文件最主要的作用就是保存数据,它既可以保
  • 花7万退货退款无门:谁在纵容淘宝珠宝商家造假?

    花7万退货退款无门:谁在纵容淘宝珠宝商家造假?

    来源:极点商业作者:杨铭在淘宝购买珠宝玉石后,因为保证金不够赔付,店铺关闭,退货退款难、维权无门的比比皆是。&ldquo;提供相关产品鉴定证书,支持全国复检,可以30天无理由退换货。&
  • 年轻人的“职场羞耻感”,无处不在

    年轻人的“职场羞耻感”,无处不在

    作者:冯晓亭 陶 淘 李 欣 张 琳 马舒叶来源:燃次元&ldquo;人在职场,应该选择什么样的着装?&rdquo;近日,在网络上,一个与着装相关的帖子引发关注,在该帖子里,一位在高级写字楼亚洲金
  • 联想的ThinkBook Plus下一版曝光,键盘旁边塞个平板

    联想的ThinkBook Plus下一版曝光,键盘旁边塞个平板

    ThinkBook Plus 是联想的一个特殊笔记本类别,它在封面放入了一块墨水屏,也给人留下了较为深刻的印象。据有人爆料,联想的下一款 ThinkBook Plus 可能更特殊,它
  • 世界人工智能大会国际日开幕式活动在世博展览馆开启

    世界人工智能大会国际日开幕式活动在世博展览馆开启

    30日上午,世界人工智能大会国际日开幕式活动在世博展览馆开启,聚集国际城市代表、重量级院士专家、国际创新企业代表,共同打造人工智能交流平台。上海市副市
Top