Java虚拟线程——Project Loom带来的并发革命

简介: 虚拟线程(Virtual Threads)是Java 21中最引人注目的特性,也是Project Loom的核心成果。

虚拟线程(Virtual Threads)是Java 21中最引人注目的特性,也是Project Loom的核心成果。虚拟线程解决了传统Java并发模型的根本矛盾:线程是昂贵的操作系统资源,但高并发应用需要大量线程来处理阻塞I/O操作。虚拟线程将线程的创建成本降低了数千倍,使百万并发成为现实。
参考:https://vhjpe.cn/category/chanpin-pingce.html

传统线程模型的困境:Java的Thread从1.0开始就映射到操作系统线程(OS线程)。OS线程的创建成本高(约1MB栈内存),上下文切换开销大,数量受限(通常几千到几万)。这意味着传统的“一个请求一个线程”模型无法支撑C10K问题。为了解决这个问题,开发者被迫使用异步编程(NIO、Netty、CompletableFuture),牺牲了代码的可读性和可维护性。

虚拟线程是JVM管理的轻量级线程,不直接映射到OS线程。多个虚拟线程可以运行在同一个OS线程(称为载体线程)上。当虚拟线程执行阻塞操作(如socket.read())时,它会从载体线程上卸载(yield),载体线程切换到另一个可运行的虚拟线程。当I/O完成后,虚拟线程被重新挂载到某个载体线程上继续执行。

虚拟线程的调度由JVM的FIFO任务队列实现。调度器使用ForkJoinPool(固定大小的work-stealing池)作为载体线程池。虚拟线程的栈帧存储在堆上(而不是OS线程的栈中),因此可以轻松支持数百万个虚拟线程,每个虚拟线程的初始栈大小可配置(通常几百字节)。

虚拟线程的API与普通线程几乎相同。创建虚拟线程:Thread.startVirtualThread(runnable)或Thread.ofVirtual().start(runnable)。Executors.newVirtualThreadPerTaskExecutor()返回一个为每个任务创建新虚拟线程的执行器。虚拟线程也支持ThreadLocal、InheritableThreadLocal,但使用ThreadLocal时需要谨慎——因为虚拟线程数量巨大,ThreadLocal可能消耗大量内存。
参考:https://vhjpe.cn/category/meirong-zhishi.html

虚拟线程与平台线程的对比:虚拟线程适合执行大量阻塞I/O操作的任务,不适合CPU密集型任务(如果虚拟线程一直运行而不阻塞,调度器无法切换,一个载体线程只能运行一个虚拟线程)。虚拟线程的创建和切换成本比平台线程低几个数量级,但比异步回调稍高。

虚拟线程与现有框架的集成:Tomcat、Jetty、Netty等框架正在适配虚拟线程。Tomcat已经支持虚拟线程作为请求处理线程。Spring Framework 6和Spring Boot 3提供了对虚拟线程的一等支持——@Async方法可以在虚拟线程上执行。JDBC驱动需要适配虚拟线程,因为传统的JDBC驱动会阻塞载体线程,抵消虚拟线程的优势。

虚拟线程的注意事项:同步块和同步方法可能导致载体线程被固定(pinned),即使虚拟线程阻塞,载体线程也无法切换。JVM会检测这种情况并增加载体线程数量作为缓解,但性能会下降。解决方案是使用ReentrantLock替代synchronized。本地方法和外部函数(FFI)也会导致固定。ThreadLocal的使用需要重新评估,因为虚拟线程数量大,ThreadLocal的内存占用会放大。线程池的概念需要调整——传统的线程池限制了并发数,但虚拟线程池的核心目标是创建新线程,而不是复用线程。

虚拟线程的性能特征:创建100万个虚拟线程只需几秒(而平台线程需要几分钟或直接失败)。虚拟线程的阻塞切换开销约为几微秒,远低于平台线程的上下文切换(微秒到毫秒级)。虚拟线程的内存占用约为几百字节(平台线程约1MB)。虚拟线程的启动时间约为1-2微秒(平台线程约1毫秒)。

虚拟线程对编程模型的影响:虚拟线程最重要的贡献是让阻塞重新变得可接受。开发者可以回到简单直接的“一个请求一个线程”模型,在需要I/O时直接阻塞,而不必编写复杂的异步代码。这大大降低了并发编程的门槛,也使代码更容易调试和维护。
参考:https://vhjpe.cn/category/hufu-jiqiao.html

结构化并发是虚拟线程的自然延伸。结构化并发将并发任务组织为树状结构,确保子任务的生命周期不会超出父任务的范围。StructuredTaskScope(预览功能,Java 21)提供了结构化并发的API。结构化并发的好处包括:自动取消(如果父任务失败,所有子任务被取消)、错误隔离、以及资源泄漏防止。

作用域值(Scoped Values,Java 20预览,Java 21孵化)是ThreadLocal的替代方案,专为虚拟线程设计。作用域值是不可变的,只能在有限的作用域内设置,在线程间传递。与ThreadLocal不同,作用域值不会在虚拟线程数量巨大时导致内存泄漏,且传递效率更高。

虚拟线程的限制:虚拟线程不能与ThreadGroup一起使用(已过时)。虚拟线程不支持stop、suspend、resume等已废弃的方法。虚拟线程的优先级被忽略。虚拟线程的调试工具(如JDB、JMC)正在逐步适配。

虚拟线程的启用:Java 21中虚拟线程是正式功能,无需预览标志。迁移现有代码通常只需将Executors.newCachedThreadPool()替换为Executors.newVirtualThreadPerTaskExecutor()。但需要注意依赖库的兼容性——某些库可能在虚拟线程中表现异常。

虚拟线程的未来:虚拟线程是Java并发模型的最大变革,它将改变服务端Java的编程范式。随着生态系统对虚拟线程的适配,我们可以期待:Web框架默认使用虚拟线程处理请求;数据库驱动支持真正的异步I/O(不阻塞载体线程);以及更简单的并发编程模型,无需理解Reactor、RxJava或CompletableFuture。

虚拟线程不是银弹。它最适合I/O密集型应用,如Web服务、微服务、API网关。对于CPU密集型应用(如视频编码、机器学习),传统平台线程仍然是最佳选择。但大多数Java应用都是I/O密集型的——它们花大量时间等待数据库、缓存、消息队列和外部服务。对于这些应用,虚拟线程将带来显著的简化,而不仅仅是性能提升。
参考:https://vhjpe.cn/

目录
相关文章
|
4月前
|
人工智能 Java API
【SpringAIAlibaba新手村系列】(18)Agent 智能体与今日菜单应用
本章以 ReactAgent 为入口,将本地菜单工具与 MCP 外部工具合并注册,统一通过 /eatAgent 执行任务,展示 Agent 在多工具协同下的意图理解、工具调用与结果整合能力。
700 3
|
Java 数据库连接 mybatis
MyBatis中支持的JdbcType 和JavaType
MyBatis中支持的JdbcType 和JavaType
1181 3
|
安全 BI API
WhatsApp的名词都是什么意思?从个人账号到商业平台全解析
WhatsApp、WhatsApp Business API、WhatsApp Business 、Meta 蓝标、这些分别都是什么意思,有哪些区别?
3091 0
|
6月前
|
存储 Java 中间件
Java 虚拟线程:JDK21 轻量级并发革命
JDK21正式引入的虚拟线程是Java并发模型的革命性升级:轻量(百字节/个)、百万级可扩展、JVM自主调度、零OS上下文切换,完美解决传统平台线程内存高、并发低、调优难痛点,尤其适用于IO密集型微服务与网关场景。
698 4
|
NoSQL 安全 Java
2.2k star 单点登录框架揭秘!主流SSO太重?SpringBoot轻量级Smart‑SSO轻松接入·分布式·强踢人
Smart-SSO 是一个基于 SpringBoot 的轻量级单点登录框架,采用 OAuth2 授权码与 RBAC 权限设计,解决跨域认证、单点退出、令牌过期等痛点。支持自动续签、强制踢人、按钮级权限控制及分布式部署,适合中小团队快速构建高可用认证中台。项目已获 2.2k Star,代码开源,接入简单,是企业级应用的理想选择。[详情见 GitHub](https://github.com/a466350665/smart-sso)。
759 23
|
Java API 调度
从阻塞到畅通:Java虚拟线程开启并发新纪元
从阻塞到畅通:Java虚拟线程开启并发新纪元
542 83
|
9月前
|
缓存 架构师 容灾
【架构师】什么是单元化架构?
单元化架构将系统划分为多个自包含单元,每个单元独立部署全套业务与部分数据,支持就近访问、低延迟与异地多活。用户请求在单个单元内闭环完成,提升性能与容灾能力,但需全链路改造、面临数据路由与高成本挑战,适用于大型企业核心场景。
727 1
|
11月前
Vite使用svg-企业级开发(支持本地svg和网络svg渲染)
本教程介绍如何在Vite项目中集成SVG图标插件。首先安装`vite-plugin-svg-icons`,配置插件指向SVG图标目录,并注册全局组件。接着创建SVG图标组件,支持内部图标与外部图片展示。通过简单配置,即可在页面中灵活使用各类SVG图标,提升开发效率。
548 0
|
监控 Java 编译器
聊聊JVM如何优化
JVM的优化是一个复杂而细致的过程,涉及内存管理、垃圾回收、即时编译、线程调度等多个方面。通过合理配置JVM参数、选择合适的垃圾回收器、优化线程调度和使用专业的监控工具,可以大幅提升Java应用的性能和稳定性。掌握这些优化技巧,能够帮助开发者在高并发、高负载的生产环境中保持系统的高效运行。
889 13
|
缓存 Java 应用服务中间件
Java虚拟线程探究与性能解析
本文主要介绍了阿里云在Java-虚拟-线程任务中的新进展和技术细节。
1167 23

热门文章

最新文章