当前位置: 首页 > news >正文

虚拟线程和普通线程的区别

虚拟线程

虚拟线程(Virtual Threads)是 Java 21 中引入的一项革命性特性,它旨在从根本上改变我们处理高并发应用程序的方式。

简单来说,它们的优势和区别可以从一个比喻开始:

  • 平台线程(普通线程)就像真正的工人。操作系统招募一个工人(创建线程),这个工人会亲自去完成一项任务(执行代码)。工人数量有限(一台机器最多几千个),而且招募和开除工人(创建和销毁线程)开销很大。
  • 虚拟线程就像一份份任务清单。一个工人(平台线程)可以拿着许多份任务清单(虚拟线程)。当某份清单上的任务需要等待(比如等网络响应、等数据库查询),工人就把它暂时放到一边,拿起另一份清单继续工作。一个工人可以高效地处理成千上万份清单

下面我们来详细对比它们的优势和区别。


核心优势对比表

特性平台线程(普通线程)虚拟线程
本质操作系统线程的包装器(1:1 映射)。是重量级的资源。Java 运行时管理的轻量级用户态线程(M:N 映射)。
资源开销。每个线程都有自己的大栈(默认为1MB)、PC寄存器等。受操作系统限制。极小。初始栈很小(约几百字节),按需扩容。
数量限制有限(通常几千个)。受限于内存和操作系统配置。创建太多会耗尽内存或导致线程切换开销巨大。海量(轻松数百万个)。只受限于堆内存大小,可以创建极其大量的虚拟线程。
创建与销毁昂贵。创建和销毁成本高,通常需要池化(如使用 ExecutorService)来避免开销。廉价。创建和销毁成本极低,通常不需要池化。可以为每个任务创建一个新的虚拟线程。
阻塞开销极其昂贵。当一个平台线程阻塞(如等待I/O)时,这个宝贵的系统资源就被挂起,什么也不做,但依然占用着内存和CPU调度资源。几乎为零。当虚拟线程阻塞时,它会自动从平台线程上卸载(yield),这个平台线程立即可以去执行其他就绪的虚拟线程。阻塞的操作完成后,虚拟线程再被调度到某个平台线程上继续执行。
调试与监控传统工具(如线程转储、JProfiler)工作良好。需要支持虚拟线程的工具(新版JDK工具已支持)。线程转储可以包含数百万个虚拟线程,但提供了新的格式(jcmd <pid> Thread.dump_to_file -format=json <file>)来管理。
适用场景CPU密集型计算(充分利用多核)。高并发I/O密集型任务(Web服务器、微服务、数据库调用、消息队列等)。这是虚拟线程的主场。

虚拟线程的三大核心优势

  1. 极高的并发规模与资源效率

    • 问题:在传统的“一个请求一个线程”的Web服务器模型中,线程数限制了并发连接数。1万个并发请求就需要1万个线程,这会给操作系统带来巨大压力。
    • 解决方案:使用虚拟线程,你可以用少量平台线程(如CPU核心数)来处理数百万个并发连接。每个连接都可以分配一个虚拟线程,当它们等待网络I/O时,会自动让出执行权,从而让宝贵的平台线程始终处于工作状态。
  2. 简化的编程模型(告别回调地狱)

    • 问题:为了应对平台线程的瓶颈,开发人员采用了异步编程(如 CompletableFuture)或反应式编程(如 Project Reactor)。这些模式性能很好,但代码难以编写、调试和维护(俗称“回调地狱”)。
    • 解决方案:虚拟线程允许你用简单的同步、阻塞式的代码风格,写出高性能的异步应用程序。你不再需要学习复杂的异步API,只需像写最传统的代码一样,自然地使用 Thread.sleep()synchronized、阻塞式I/O等,而底层由虚拟线程帮你高效地处理阻塞。

    代码对比示例:处理多个HTTP请求

    • 传统方式(使用平台线程池)

      java

      // 线程池大小有限,大量请求会被排队或拒绝
      ExecutorService executor = Executors.newFixedThreadPool(200);
      for (String url : urls) {executor.submit(() -> {// 阻塞操作,占用一个宝贵的线程String result = HttpClient.newHttpClient().send(request, BodyHandlers.ofString());process(result);});
      }
      
    • 虚拟线程方式

      java

      // 为每个任务创建一个虚拟线程,成本极低
      for (String url : urls) {Thread.ofVirtual().start(() -> {// 写法是同步阻塞的,但底层是非阻塞的!String result = HttpClient.newHttpClient().send(request, BodyHandlers.ofString());process(result);});
      }
      

      上面的代码看起来像是创建了成千上万个线程,但实际上只使用了少量平台线程,效率极高。

  3. 与现有代码的完美兼容性

    • 虚拟线程是 Thread 类的实现。这意味着绝大多数现有的Java代码和库(如JDBC、HTTP客户端、同步代码块)无需任何修改就能在虚拟线程上运行并立即获益。这降低了 adoption 的成本。

需要注意的地方(并非银弹)

  • 不适用于CPU密集型任务:如果你的任务是纯计算、持续占用CPU的,那么虚拟线程不会带来性能提升。此时,平台线程的数量仍然应该约等于CPU核心数,以最大化计算能力。虚拟线程的优势在于等待(I/O、锁、睡眠等)。
  • 对原生代码和synchronized的考量:如果一个虚拟线程在synchronized块内或执行本地(JNI)代码时被阻塞,它所承载的平台线程也会被阻塞(这被称为“引脚”,pinning)。虽然新版JDK也在优化这一点,但大量使用 synchronized 可能会限制虚拟线程的可扩展性。建议优先使用 java.util.concurrent 包中的锁(如 ReentrantLock),它们在虚拟线程中能够正确地被卸载。

总结

方面结论
核心优势用同步的代码,获异步的性能。极大地提升了I/O密集型应用的并发能力、资源利用率和开发效率。
变革性它让Java在高并发编程领域重新变得简单,有望取代许多复杂的异步编程模式,回归到直观的指令式编程。
使用建议对于新的I/O密集型项目,强烈建议使用虚拟线程。对于现有项目,可以几乎无成本地尝试将其线程池替换为虚拟线程,以获得潜在的巨大性能提升。

可以将虚拟线程理解为Java为现代云原生和微服务架构提供的一项“基础设施”,它让开发者不再需要为了性能而牺牲代码的可读性和可维护性。


文章转载自:

http://wHGdHJz5.wnkqt.cn
http://0d2LS0FB.wnkqt.cn
http://Er1m3HJl.wnkqt.cn
http://fQifU0t6.wnkqt.cn
http://3ebRHr1s.wnkqt.cn
http://iqNDl8LO.wnkqt.cn
http://t682fZCx.wnkqt.cn
http://cVUm2ir4.wnkqt.cn
http://8GMoPukI.wnkqt.cn
http://jxVV6pGL.wnkqt.cn
http://yGFnkrir.wnkqt.cn
http://tImTrqHS.wnkqt.cn
http://tU7rC0k2.wnkqt.cn
http://7Wh7MXnI.wnkqt.cn
http://JKsj8ZJ3.wnkqt.cn
http://tFMyvElW.wnkqt.cn
http://JIlf6sVi.wnkqt.cn
http://LQ0NLqrE.wnkqt.cn
http://KM47vFaA.wnkqt.cn
http://xFE7LWqc.wnkqt.cn
http://94RHpE0F.wnkqt.cn
http://SvVl0sUy.wnkqt.cn
http://wSHu15bs.wnkqt.cn
http://GfRE1PcR.wnkqt.cn
http://n7uwdqjW.wnkqt.cn
http://EqJnhGoh.wnkqt.cn
http://BFs4ZkWa.wnkqt.cn
http://gPJ2bTdh.wnkqt.cn
http://cr0fQC6e.wnkqt.cn
http://Jk1EESMs.wnkqt.cn
http://www.dtcms.com/a/384751.html

相关文章:

  • 微软发布高危漏洞更新,涉及 Windows、Office、SQL Server 等多款产品
  • IDEA-MyBatis动态sql关联映射
  • 【学习】【js】栈数据结构
  • Coze源码分析-资源库-创建知识库-后端源码-核心技术与总结
  • ArcGIS Pro实现基于 Excel 表格批量创建标准地理数据库(GDB)——高效数据库建库解决方案
  • 在openEuler系统 上安装Go语言开发环境
  • 奈奎斯特频率和采样定理的解释
  • 直播APP集成美颜SDK详解:智能美妆功能的开发实战
  • 基于Matlab GUI的心电信号QRS波群检测与心率分析系统
  • 贪心算法应用:5G网络切片问题详解
  • 【117】基于51单片机GSM智能拐杖老人防跌倒报警器【Keil程序+报告+原理图】
  • Rancher 社区双周报|聚焦 Harvester 新特性:网络、存储与虚拟化全面升级
  • CSS视差旋转动效实战
  • Java 设计模式——单例模式6种写法:从原理到 SpringBoot 落地
  • 【自存】懒汉式单例模式中的多线程经典问题
  • 【第五章:计算机视觉-项目实战之图像分类实战】1.经典卷积神经网络模型Backbone与图像-(4)经典卷积神经网络ResNet的架构讲解
  • 区块链:搭建简单以太坊Geth私有链
  • 数据分析:函数
  • 《投资-57》元宇宙的价值
  • Linux任务调度全攻略
  • 基于springboot的毕业旅游一站式定制系统
  • 创建其他服务器账号
  • 前端-详解ref和$refs
  • C++---变量的多维分类
  • Vue 3 前端工程化规范
  • NLP Subword 之 WordPiece 算法原理
  • 【SQL】MySQL中空值处理COALESCE函数
  • Kafka实时数据管道:ETL在流式处理中的应用
  • VBA数据结构深度解析:字典对象与集合对象的性能终极对决
  • 查看当前虚拟环境中安装的 PyTorch 版本