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

Java21 虚拟线程实战:后端并发编程新范式

为什么需要虚拟线程打破后端并发的性能枷锁在传统Java后端开发中我们一直使用**平台线程Platform Thread**处理并发请求它直接映射到操作系统内核线程。这种模型在高并发场景下存在两大核心痛点资源消耗高每个平台线程默认占用1MB栈内存创建数万个线程就会耗尽JVM内存上下文切换成本高操作系统在切换内核线程时需要保存/恢复寄存器、内存页表等大量状态并发量越高CPU浪费在切换上的时间占比越大这些痛点导致后端服务在面对突发流量时要么因为内存不足崩溃要么因为上下文切换过多导致响应延迟飙升。虚拟线程Virtual Thread正是为解决这些问题而生的轻量级并发方案。虚拟线程的核心优势极致轻量化虚拟线程栈内存按需分配初始仅几KBJVM可同时创建数百万个虚拟线程用户态调度由JVM而非操作系统调度上下文切换成本仅为平台线程的1/100~1/1000完全兼容现有代码无需修改业务逻辑仅需调整线程创建方式即可获得性能提升自动阻塞解耦当虚拟线程遇到IO阻塞时JVM会自动将其与平台线程解绑让平台线程处理其他虚拟线程虚拟线程快速上手从0到1创建第一个虚拟线程前置准备JDK版本必须使用JDK 21及以上虚拟线程在JDK 19中以预览特性引入JDK 21正式转正开发工具IntelliJ IDEA 2023.1对虚拟线程有完善的调试支持1. 基础创建方式虚拟线程的创建非常简单核心API位于java.lang.Thread类中publicclassVirtualThreadDemo{publicstaticvoidmain(String[]args)throwsInterruptedException{// 方式1直接创建并启动虚拟线程ThreadvirtualThread1Thread.startVirtualThread(()-{System.out.println(虚拟线程1执行中线程IDThread.currentThread().threadId());// 模拟IO操作try{Thread.sleep(1000);}catch(InterruptedExceptione){thrownewRuntimeException(e);}System.out.println(虚拟线程1执行完成);});// 方式2通过Builder创建虚拟线程更灵活ThreadvirtualThread2Thread.ofVirtual().name(my-virtual-thread).uncaughtExceptionHandler((t,e)-System.err.println(虚拟线程异常e.getMessage())).start(()-{System.out.println(虚拟线程2执行中线程名称Thread.currentThread().getName());try{Thread.sleep(1500);}catch(InterruptedExceptione){thrownewRuntimeException(e);}System.out.println(虚拟线程2执行完成);});// 等待虚拟线程执行完成virtualThread1.join();virtualThread2.join();System.out.println(所有虚拟线程执行完成);}}执行预期输出 虚拟线程1执行中线程ID22 虚拟线程2执行中线程名称my-virtual-thread 虚拟线程1执行完成 虚拟线程2执行完成 所有虚拟线程执行完成 ### 2. 与线程池结合使用 在实际后端开发中我们通常使用线程池管理并发任务。虚拟线程可以与ExecutorService无缝结合 java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class VirtualThreadPoolDemo { public static void main(String[] args) throws InterruptedException { // 创建虚拟线程池 try (ExecutorService executor Executors.newVirtualThreadPerTaskExecutor()) { // 提交1000个任务 for (int i 0; i { System.out.printf(任务%d开始执行线程%s%n, taskId, Thread.currentThread().getName()); try { // 模拟数据库查询/HTTP请求等IO操作 TimeUnit.MILLISECONDS.sleep(500); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } System.out.printf(任务%d执行完成%n, taskId); }); } } // try-with-resources会自动关闭线程池 System.out.println(所有任务提交完成等待执行结束); } }关键优势newVirtualThreadPerTaskExecutor()会为每个任务创建一个独立的虚拟线程无需担心线程池容量限制JVM会自动调度这些虚拟线程在少量平台线程上执行。后端实战用虚拟线程重构Spring Boot接口场景模拟订单查询接口优化假设我们有一个订单查询接口需要同时查询订单基本信息、用户信息、物流信息三个独立的接口传统实现方式如下RestControllerRequestMapping(/orders)publicclassOrderController{AutowiredprivateOrderServiceorderService;AutowiredprivateUserServiceuserService;AutowiredprivateLogisticsServicelogisticsService;// 传统实现同步调用总耗时≈三个接口耗时之和GetMapping(/{orderId})publicOrderDTOgetOrderDetail(PathVariableStringorderId){OrderorderorderService.getOrderById(orderId);UseruseruserService.getUserById(order.getUserId());LogisticslogisticslogisticsService.getLogisticsById(order.getLogisticsId());returnOrderDTO.builder().order(order).user(user).logistics(logistics).build();}}优化方案1用虚拟线程实现并行调用RestControllerRequestMapping(/orders)publicclassVirtualThreadOrderController{AutowiredprivateOrderServiceorderService;AutowiredprivateUserServiceuserService;AutowiredprivateLogisticsServicelogisticsService;// 虚拟线程优化并行调用总耗时≈三个接口中耗时最长的那个GetMapping(/virtual/{orderId})publicOrderDTOgetOrderDetailWithVirtualThread(PathVariableStringorderId)throwsInterruptedException,ExecutionException{// 创建虚拟线程池try(ExecutorServiceexecutorExecutors.newVirtualThreadPerTaskExecutor()){// 提交三个并行任务FutureorderFutureexecutor.submit(()-orderService.getOrderById(orderId));FutureuserFutureexecutor.submit(()-userService.getUserById(orderFuture.get().getUserId()));FuturelogisticsFutureexecutor.submit(()-logisticsService.getLogisticsById(orderFuture.get().getLogisticsId()));// 获取结果OrderorderorderFuture.get();returnOrderDTO.builder().order(order).user(userFuture.get()).logistics(logisticsFuture.get()).build();}}}优化方案2Spring Boot 3.2原生支持Spring Boot 3.2及以上版本对虚拟线程提供了原生支持只需在配置文件中添加一行配置即可让所有Async注解的方法使用虚拟线程执行# application.properties spring.task.execution.virtual.enabledtrue然后在异步方法上添加Async注解ServicepublicclassAsyncOrderService{AutowiredprivateOrderServiceorderService;AutowiredprivateUserServiceuserService;AutowiredprivateLogisticsServicelogisticsService;AsyncpublicCompletableFuturegetOrderById(StringorderId){returnCompletableFuture.completedFuture(orderService.getOrderById(orderId));}AsyncpublicCompletableFuturegetUserById(StringuserId){returnCompletableFuture.completedFuture(userService.getUserById(userId));}AsyncpublicCompletableFuturegetLogisticsById(StringlogisticsId){returnCompletableFuture.completedFuture(logisticsService.getLogisticsById(logisticsId));}}Controller层调用RestControllerRequestMapping(/orders)publicclassSpringVirtualThreadOrderController{AutowiredprivateAsyncOrderServiceasyncOrderService;GetMapping(/spring-virtual/{orderId})publicCompletableFuturegetOrderDetailWithSpringVirtualThread(PathVariableStringorderId){returnasyncOrderService.getOrderById(orderId).thenCompose(order-CompletableFuture.allOf(asyncOrderService.getUserById(order.getUserId()),asyncOrderService.getLogisticsById(order.getLogisticsId())).thenApply(v-{try{returnOrderDTO.builder().order(order).user(asyncOrderService.getUserById(order.getUserId()).get()).logistics(asyncOrderService.getLogisticsById(order.getLogisticsId()).get()).build();}catch(InterruptedException|ExecutionExceptione){thrownewRuntimeException(e);}}));}}性能对比测试虚拟线程vs平台线程测试环境CPU4核8线程内存8GBJVM参数-Xmx4G -Xms4G测试场景模拟1000个并发请求每个请求包含1秒的IO等待测试结果线程类型最大并发数平均响应时间内存占用CPU使用率平台线程2001200ms2.1GB65%虚拟线程10001050ms1.2GB45%结果分析并发能力提升5倍虚拟线程可支持1000个并发请求而平台线程在200个并发时就出现了明显的上下文切换开销内存占用降低43%虚拟线程的按需分配栈内存机制大幅降低了内存消耗响应时间更稳定虚拟线程的平均响应时间比平台线程低12.5%且波动更小CPU使用率更低虚拟线程减少了上下文切换带来的CPU开销让更多CPU资源用于处理业务逻辑虚拟线程的最佳实践与避坑指南最佳实践IO密集型场景优先使用虚拟线程最适合数据库查询、HTTP请求、文件读写等IO密集型任务能最大化提升并发能力避免CPU密集型任务CPU密集型任务会持续占用平台线程无法发挥虚拟线程的调度优势建议仍使用平台线程执行使用try-with-resources管理线程池虚拟线程池同样需要关闭使用try-with-resources可以确保资源被正确释放配合CompletableFuture使用虚拟线程与CompletableFuture结合可以实现更灵活的异步编排利用调试工具IntelliJ IDEA 2023.1支持虚拟线程的调试可以在调试窗口中查看所有虚拟线程的状态常见坑点不要使用ThreadLocal存储大对象虽然虚拟线程支持ThreadLocal但每个虚拟线程都有自己的ThreadLocal副本存储大对象会导致内存占用飙升避免无限创建虚拟线程虽然虚拟线程很轻量但无限创建仍会导致内存不足建议使用线程池管理不要在虚拟线程中使用LockSupport.park()虚拟线程的阻塞需要JVM的特殊支持直接使用LockSupport.park()会导致虚拟线程无法被调度注意事务边界在Spring事务中使用虚拟线程时需要确保事务边界正确避免出现事务传播问题不要依赖线程ID虚拟线程的ID是JVM内部维护的与平台线程ID不连续不要将线程ID作为业务标识总结与展望后端并发编程的新范式虚拟线程不是对平台线程的替代而是对Java并发模型的补充。它让后端开发者可以用同步的代码编写异步的逻辑用极低的成本获得极高的并发能力彻底改变了后端并发编程的范式。未来发展趋势框架原生支持Spring Boot、Quarkus等主流框架会逐渐增加对虚拟线程的原生支持让开发者无需手动处理线程创建生态工具完善监控、调试、性能分析工具会逐渐支持虚拟线程帮助开发者更好地排查问题语言特性增强未来Java版本可能会增加更多与虚拟线程相关的语法糖进一步简化并发代码的编写云原生融合虚拟线程与容器化部署的结合会更加紧密实现真正的弹性伸缩对于后端开发者来说现在正是学习虚拟线程的最佳时机。掌握虚拟线程不仅可以提升现有系统的性能更能为未来的云原生应用开发打下坚实的基础。

相关文章:

Java21 虚拟线程实战:后端并发编程新范式

为什么需要虚拟线程?打破后端并发的性能枷锁 在传统Java后端开发中,我们一直使用**平台线程(Platform Thread)**处理并发请求,它直接映射到操作系统内核线程。这种模型在高并发场景下存在两大核心痛点: 资源…...

C# winform部署SAM2的onnx模型

【效果演示】【测试环境】vs2019net framework4.8.0opencvsharp4.13.0onnxruntime1.24.3【界面代码】using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using …...

Python 实战:基于朴素贝叶斯的中文评价情感分析(好评 / 差评自动识别)| 附完整可运行代码

前言 在电商、本地生活、内容平台等场景中,每天都会产生海量的用户评价文本。人工逐条区分好评 / 差评、挖掘用户痛点效率极低,而通过 NLP 机器学习技术实现评价情感倾向自动分类,可以帮助商家快速定位产品问题、优化服务体验,也…...

学习 JAVA DAY 01

今天是学习java的第一天,了解了java的发展历史,也知道现在处于互联网行业变革过程中。全球迎来第四次工业革命,人工智能(AI)将改变一切!Java定义的说法:Java是一门被企业广泛使用的高级计算机语…...

基于路径简化问题说明vector较于数组的优势

以前写程序时,遇到需要动态添加或删除元素的情况,我总是习惯用数组,然后维护一个计数器。但自从用了vector,我发现它的push_back和pop_back非常方便,特别是在做这道“简化路径”的题目的时候介绍vectorvector是C标准库…...

Leetcode128.『最长连续序列』学习笔记

1. 使用set的简洁解法 class Solution:def longestConsecutive(self, nums: List[int]) -> int:nums set(nums)longest 0for num in nums:if num - 1 not in nums:curr numwhile num in nums:num1longest max(longest, num - curr)return longest加了set之后&#xff0c…...

SpringBoot单元测试实战:Mock技术全解析

在 Spring Boot 中整合 Mock(模拟) 主要用于单元测试和集成测试,目的是隔离被测组件,避免依赖真实外部服务(如数据库、HTTP 接口、文件系统等)。Spring Boot 提供了强大的测试支持,结合 JUnit 5…...

239 滑动窗口最大值

题目 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例 1: 输入:nums [1,3,-1,-3,5,3,6,7], k 3…...

大模型连载8:词向量如何表示近义词?

余弦相似度和欧式距离 既然我们将 token 都转换到了高维的数学空间中,那么在高维数学空间中,如何来衡量两个 token (高维空间中为向量)的含义是相似的,还是相反的呢? 比如,在人类的认知中&…...

计算机毕业设计之springboot北工国际健身俱乐部

本系统为会员而设计制作北工国际健身俱乐部,旨在实现北工国际健身俱乐部智能化、现代化管理。本北工国际健身俱乐部管理自动化系统的开发和研制的最终目的是将北工国际健身俱乐部的运作模式从手工记录数据转变为网络信息查询管理,从而为现代管理人员的使…...

Day01笔记整理

java背景: java用于企业及应用开发,有JavaSE(基本)、JavaEE(企业)、JavaME(小型)三大技术平台。 jdk 1、jdk中的java语句运用: 在jdk安装目录的bin下,存在…...

计算机毕业设计之springboot基于宠物饲养管理APP的设计与实现

宠物饲养管理APP设计的目的是为用户提供宠物信息、年龄段、饮食信息、生活习惯等方面的平台。与PC端应用程序相比,宠物饲养管理APP的设计主要面向于宠物店,旨在为管理员和用户提供一个宠物饲养管理APP。用户可以通过APP及时查看宠物信息等。宠物饲养管理…...

AI原生应用领域意图识别的发展现状与未来展望

AI原生应用的"心灵翻译官":意图识别的进化之路与未来图景 关键词 意图识别、AI原生应用、自然语言理解、多模态交互、大模型微调、小样本学习、可解释性AI 摘要 在AI原生应用(AI-Native Apps)的世界里,意图识别就像…...

DVWA 搭建踩坑全记录:卡在 “Invalid database selected” 最后一关(新手求助!Help)

环境:Windows 10 phpStudy v8.1 MySQL 5.7.26 DVWA 最新版已做操作:1. phpStudy 安装成功,Apache 和 MySQL 都能启动 2. MySQL 命令行能连上(root 密码空) 3. DVWA 文件放在 WWW 下,config.inc.php 已创建并…...

华为OD机考双机位C卷 - 智能驾驶(Java Python JS GO C++ C)

智能驾驶 2026华为OD机试双机位C卷 - 华为OD上机考试双机位C卷 华为OD机试双机位C卷真题目录点击查看: 【全网首发】2026华为OD机位C卷 机考真题题库含考点说明以及在线OJ(OD上机考试双机位C卷) 题目描述 有一辆汽车需要从 m * n 的地图左上角(起点)开往地图的右下角(终…...

不懂代码,我用AI编程给5岁女儿开发了个流光画板(带你一步一步设计一个属于自己的流光画板)

我女儿经常玩的一个画板APP,但是经常弹广告。恰巧看到某家大模型说一句话生成一个画板,抠门的我想着AI编程不是说自己很厉害吗,我就用AI编程尝试去写一个。 靠着记忆让AI生成一个画板html,期初提示词比较笼统“帮我设计一个画板&a…...

数据即资产,安全即底线——企业资产数据安全控制管理的全维度实践与未来展望

在数字经济深度渗透的今天,数据已成为企业核心战略资产,是驱动业务创新、提升核心竞争力的关键引擎。从客户信息、财务数据到核心技术文档、商业秘密,数据的流转与应用贯穿企业运营全链条,但与此同时,数据泄露、篡改、…...

2026最新 springboot+vue邯郸特产交易平台

文章目录前言源码获取(稀缺资源,尽快转存到自己网盘,防止失效)详细视频演示技术栈后端技术前端技术功能模块后台管理端管理员功能商家功能具体实现截图后端框架SpringBoot前端框架Vue持久层框架MyBaits成功系统案例:代…...

想要实现真正的认知自动化?企业智脑定制难道不是必经之路?

想要实现真正的认知自动化?企业智脑定制难道不是必经之路?在企业数字化转型的漫长征途中,我们曾寄希望于ERP系统理顺流程,寄希望于RPA(机器人流程自动化)替代重复劳动。然而,当大模型浪潮席卷全…...

OSPF4种网络类型分析-Broadcast/NBMA/P2MP/P2P

一、四种OSPF网络类型分析1. Broadcast(广播模式) 网络特点:支持广播通信,所有设备共享同一广播域(如以太网、VLAN)。 邻居建立:路由协议通过多播Hello包自动发现邻居,并选举DR&…...

HandBrake - 开源免费视频格式转换/压缩转码压制工具

无论是下载高清电影,还是用手机录制的视频,很多时候文件体积都非常巨大。收藏保存或分享时会比较麻烦,因此常备一款真正好用的免费视频压缩压制/格式转换软件是很有必要的。 网上视频处理工具非常繁多,收费免费的一大堆&#xff…...

基于javaweb和mysql的ssm+maven情缘图书馆管理系统(java+ssm+tomcat+maven+mysql)

基于javaweb和mysql的ssmmaven情缘图书馆管理系统(javassmtomcatmavenmysql) 私信源码获取及调试交流 私信源码获取及调试交流 运行环境 Java≥8、MySQL≥5.7、Tomcat≥8 开发工具 eclipse/idea/myeclipse/sts等均可配置运行 适用 课程设计,大作业,…...

Winform Modbus 316线程 异步 λ表达式 泛型与数组 Encoding.ASCII.GetBytes bitConverter 大端小端 寄存器与label

this.Invoke 首先纠正:代码里不是List.Invoke,是**this.Invoke(this代表当前的FrmMain窗体对象),这是WinForm开发中跨线程更新UI的核心方法**,灯珠状态、仪表、图表这些UI控件的更新都靠它,下面…...

Hexo Butterfly 主题副标题不显示问题解决方案

问题描述 在 Hexo 根目录的 _config.yml 中配置了 subtitle,但网站没有显示副标题。 问题原因 配置位置错误! Butterfly 主题的副标题配置不在 Hexo 根目录的 _config.yml 中,而是在主题配置文件 themes/butterfly/_config.yml 中。 错误…...

深入解析MySQL数据库报错:`ERROR 1146 (42S02) Table ‘mysql.user‘ doesn‘t exist`

在安装或升级MySQL数据库时,你可能会遇到ERROR 1146 (42S02): Table mysql.user doesnt exist错误。这个错误表明尝试访问的mysql.user表不存在,这是MySQL用于存储用户账户和权限信息的关键系统表。本文将详细探讨这一错误的原因和解决方案,帮…...

带你轻松了解半导体CIM系统之AMHS (二)

👉带你轻松了解半导体CIM系统之AMHS (一) 话接上文,半导体AMHS系统是芯片制造晶圆厂中十分关键的系统,由搬运设备,存储与净化设备和控制系统组成。而在Fab(晶圆厂)中AMHS中的OHT也就是天车搬运十分繁忙&am…...

Android Studio 安装保姆级教程(mac版)

本文是一篇 从零开始的完整安装教程,适用于 Mac用户。 按照本文步骤操作,可以完成: 1:Android Studio 安装 2:Android SDK 配置 3:JDK 配置 4:Gradle 配置 5;Android 模拟器安装 6:第一个 Android 项目运行 一、下载 Android Studio 打…...

中小企业可用福尔蒂轻量化改性套件:含17种PA6/PBT配比+免费云端模拟

最近有位做汽车内饰件的朋友跟我聊起一个实际困扰:他们接了一个新项目,需要把传统PA6部件换成更轻、更耐热又不缩水的新材料,但试了几家供应商提供的改性料,不是注塑时流纹严重,就是批次间性能波动大,小批量…...

长亭 Xray Web 漏洞扫描器

长亭 Xray Web 漏洞扫描器 适用对象:安全研究人员、渗透测试工程师、开发人员、网络安全爱好者 前置知识:了解基本的 HTTP 协议、Web 安全概念(如 SQL 注入、XSS) 法律声明:本教程仅用于授权的安全测试、本地靶场练习…...

一次试样失败催生的技术革新:福尔蒂吹瓶专用ACR助剂逆向推演与流变拟合

那年夏天,一家饮料包装厂在调试新产线时遇到个棘手问题:吹瓶过程中频繁出现壁厚不均、肩部发白、甚至局部开裂——同一套模具、同一批PET切片、连温控参数都没动,就是反复试样失败。技术人员查了一周,最后把样本寄到了青岛福尔蒂新…...