Project Loom:了解新的 Java 并发模型
mhr18 2024-12-27 16:20 11 浏览 0 评论
Loom 是 Java 和JVM生态系统中的一个较新的项目。Loom 项目由OpenJDK托管,解决了传统 Java 并发模型的局限性。特别是,它提供了一种更轻的线程替代方案,以及用于管理线程的新语言结构。虚拟线程已经是 Loom 最重要的部分,从 Java 21 开始成为 JDK 的一部分。
请继续阅读,了解 Loom 项目的概述以及它如何建议实现 Java 并发现代化。
Java中的虚拟线程
传统的 Java 并发性是通过Thread和Runnable类进行管理的,如清单 1 所示。
Thread thread = new Thread("My Thread") {
public void run(){
System.out.println("run by: " + getName());
}
};
thread.start();
System.out.println(thread.getName());
传统的 Java 并发性在简单的情况下相当容易理解,并且 Java为使用线程提供了丰富的支持。
fibers与虚拟线程
虚拟线程一度被命名为“fibers”,但为了避免与其他语言中的纤程混淆,该名称被放弃,取而代之的是“虚拟线程”。
缺点是 Java 线程直接映射到操作系统 (OS) 中的线程。这对并发 Java 应用程序的可伸缩性造成了严格的限制。它不仅意味着应用程序线程和操作系统线程之间存在一对一的关系,而且没有用于组织线程以实现最佳排列的机制。例如,密切相关的线程可能最终会共享不同的进程,而此时它们可以从共享同一进程上的堆中受益。
为了让您了解 Loom 中的变化有多么雄心勃勃,当前的 Java 线程,即使在大型服务器上,也以数千个线程计算(最多)。Loom 建议将此限制提高到数百万个线程。这对 Java 服务器可扩展性的影响是惊人的,因为标准请求处理与线程计数结合在一起。
解决方案是引入某种虚拟线程,其中 Java 线程从底层 OS 线程中抽象出来,JVM可以更有效地管理两者之间的关系。Loom 项目通过引入新的虚拟线程类来实现这一目标。由于新VirtualThread类具有与传统线程相同的 API 表面,因此很容易迁移。
延续和结构化并发
Continuations 是虚拟线程基础的低级功能。本质上,延续允许 JVM 停顿并重新启动执行流。
正如Project Loom 提案所述:
实现延续(实际上是整个项目)的主要技术任务是向 HotSpot 添加捕获、存储和恢复调用堆栈的能力,而不是作为内核线程的一部分。
Loom 的另一个功能是结构化并发,它为并发提供了线程语义的替代方案。结构化并发的主要思想是为您提供同步语法来处理异步流(类似于JavaScript 的 async 和 wait 关键字)。这对于 Java 开发人员来说是一个很大的福音,使简单的并发任务更容易表达。
如果您曾经接触过Quasar,它通过字节码操作为 Java 带来了轻量级线程,您可能还记得技术主管 Ron Pressler。Pressler 现在是 Oracle Loom 的负责人,他这样解释结构化并发:
结构化并发是一种范式,它将结构化编程的原理引入并发代码中,并使编写并发代码变得更容易,从而干净地处理并发编程中一些最棘手的长期问题:错误处理和取消。在 JDK 21 中,我们提供了StructuredTaskScope一个预览 API,为 JDK 带来了结构化编程。因为虚拟线程意味着程序中的每个并发任务都有自己的线程,虚拟线程和虚拟线程StructuredTaskScope是天作之合。除了使并发代码更容易正确编写之外,StructuredTaskScope还带来了结构化观察:捕获线程之间关系的线程转储。
虚拟线程的替代方案
在更仔细地研究 Loom 之前,我们先注意一下 Java 中针对并发性提出了多种方法。一般来说,这些相当于异步编程模型。有些(例如CompletableFutures非阻塞 IO)通过提高线程使用效率来解决边缘问题。其他的,比如RXJava(ReactiveX 的 Java 实现),是大规模的异步替代方案。
尽管 RXJava 是一种强大且具有潜在高性能的并发方法,但它也有缺点。特别是,它与 Java 开发人员传统上使用的概念模型有很大不同。而且,RXJava 无法与通过在虚拟机层管理虚拟线程实现的理论性能相匹配。
Java 的新 VirtualThread 类
如前所述,新VirtualThread类代表虚拟线程。在幕后,异步杂技正在进行中。为什么要这么麻烦,而不是在语言层面采用像 ReactiveX 这样的东西呢?答案是既让开发人员更容易理解,又让现有代码的迁移变得更容易。例如,数据存储驱动程序可以更轻松地过渡到新模型。
清单 2 显示了一个使用虚拟线程的简单示例。请注意,它与现有Thread代码非常相似。(这段代码片段来自Oracle对Loom和虚拟线程的介绍。)
清单 2. 创建虚拟线程
Thread.startVirtualThread(
() -> {
System.out.println("Hello World");
}
);
除了这个非常简单的示例之外,还有调度方面的广泛考虑因素。这些机制尚未确定,Loom 提案很好地概述了所涉及的想法。
关于 Loom 虚拟线程的一个重要注意事项是,无论整个 Java 系统需要做什么更改,都不能破坏现有代码。现有的线程代码将来将完全兼容。您可以使用虚拟线程,但不是必须的。实现这种向后兼容性是一项相当艰巨的任务,并且占用了 Loom 团队花费的大部分时间。
具有延续性的低级异步
现在我们已经了解了虚拟线程,让我们看一下仍在开发中的延续功能。Loom 支持虚拟线程和结构化并发的延续。还有人讨论将延续作为公共 API 供开发人员使用。那么,什么是延续呢?
从较高层次来看,延续是程序中执行流的代码表示。换句话说,延续允许开发人员通过调用函数来操纵执行流。Loom 文档提供了清单 3 中的示例,它提供了关于延续如何工作的良好心理图景。
清单 3. 延续的示例
foo() { // (2)
...
bar()
...
}
bar() {
...
suspend // (3)
... // (5)
}
main() {
c = continuation(foo) // (0)
c.continue() // (1)
c.continue() // (4)
}
考虑每个注释数字所描述的执行流程:
- foo(0) 从函数开始创建延续
- (1) 将控制权传递给 Continue 的入口点
- (2) 执行到下一个暂停点,即 (3)
- (3) 将控制释放回源头,位于 (1)
- (4) 现在执行,调用continue继续,流程返回到 (5) 处暂停的位置
尾调用消除
Loom 的另一个既定目标是尾部调用消除(也称为尾部调用优化)。这是所提议系统的一个相当深奥的元素。核心思想是系统将能够尽可能避免为延续分配新的堆栈。在这种情况下,执行延续所需的内存量保持一致,而不是不断构建,因为该过程中的每个步骤都需要保存先前的堆栈,并在调用堆栈展开时使其可用。
Loom 的下一步是什么
尽管 Loom 已经提供了很多值得探索的内容,但还有更多内容正在计划中。我向 Ron Pressler 询问了未来的路线图:
在短期内,我们正在努力解决可能是完全透明地采用虚拟线程的最大障碍:由于synchronized. 目前,在同步块或方法内,通常会释放底层操作系统线程的 IO 操作会阻塞它。这称为固定,如果这种情况发生得非常频繁且持续时间较长,则可能会损害虚拟线程的可扩展性优势。今天的解决方法是使用 JDK 中的观察工具识别这些实例,并用java.util.concurrent锁替换它们,这样就不会受到固定的影响。我们正在努力停止synchronized固定,以便不需要这项工作。此外,我们正在努力提高虚拟线程调度IO操作的效率,进一步提高其性能。
从中期来看,我们希望io_uring在可能的情况下合并,以提供除网络操作之外的文件系统操作的扩展。我们还希望提供自定义调度程序:虚拟线程当前由非常适合通用服务器的调度程序进行调度,但更奇特的用途可能需要其他调度算法,因此我们希望支持可插入的自定义调度程序。
进一步,我们希望添加通道(类似于阻塞队列,但具有附加操作,例如显式关闭),以及可能的生成器,就像在 Python 中一样,这使得编写迭代器变得容易。
Loom 和 Java 的未来
Loom 和 Java 通常主要致力于构建 Web 应用程序。显然,Java 还用于许多其他领域,Loom 引入的思想可能在各种应用程序中都有用。很容易看出,大幅提高线程效率并显着减少处理多个竞争需求的资源需求将如何提高服务器的吞吐量。更好地处理请求和响应对于整个现有和未来的 Java 应用程序来说是一个底线胜利。
与任何雄心勃勃的新项目一样,Loom 也并非没有挑战。处理复杂的线程交错(虚拟或其他线程)总是很复杂,我们必须等待才能确切地看到出现哪些库支持和设计模式来处理 Loom 的并发模型。
随着 Project Loom 进入 Java 的主要分支并根据现实世界的使用而不断发展,这将是一件令人着迷的事情。随着这一过程的展开,以及新系统固有的优势被应用到开发人员所依赖的基础设施中(想想像 Jetty 和Tomcat这样的 Java 应用服务器),我们可以见证 Java 生态系统发生翻天覆地的变化。
Java 和它的主要服务器端竞争对手Node.js在性能上已经不相上下。在典型的 Web 应用程序用例中,Java 性能的数量级提升可能会改变未来几年的格局。
相关推荐
- 2025最新指南:Quarkus整合Redisson,轻松玩转分布式锁!
-
分布式系统的高并发场景下,如何确保资源操作的原子性和一致性?Redisson作为Redis官方推荐的分布式锁方案,结合Quarkus的云原生特性,能实现高性能、低延迟的分布式锁管理。本文将从原理到实战...
- Linux进程上下文切换过程context_switch详解
-
1前言1.1Linux的调度器组成2个调度器可以用两种方法来激活调度一种是直接的,比如进程打算睡眠或出于其他原因放弃CPU另一种是通过周期性的机制,以固定的频率运行,不时的检测是否有必要因此...
- 开发10年面试过上千人,在网易面试Java程序员,我最爱问这些问题
-
在网易当了3年的面试官,一般在面试Java程序员的时候,我主要会从这几个角度,去问这些问题,在这篇文章中,我会用我上一位面试过程来为大家总结,我面试的时候爱问的这些问题!有需要面试的小伙伴可以参考一下...
- 电影票务APP的“座位锁定”,Redis如何避免冲突?
-
现在买电影票,真是越来越方便了!再也不用提前老半天跑去电影院排队,在手机APP上动动手指,选好场次、挑好座位,在线支付,一气呵成。尤其是遇到热门大片,或者想抢个“皇帝位”(中间靠后视野好的位置),那个...
- Serverless架构下,Redis的用武之地在哪里?
-
在云计算的演进浪潮中,Serverless(无服务器)架构无疑是一颗璀璨的明星。它将传统服务器的运维复杂性彻底“隐藏”起来,开发者只需关注核心业务逻辑,编写一个个独立的函数(Function-as-a...
- 高可用聊天系统设计方案(Hyperf实现)
-
一、系统架构设计1.分层架构图客户端↑↓HTTP/WSAPI网关层(Nginx+Keepalived)↑↓RPC业务服务集群↑↓数据层(MySQLClus...
- 大厂面试冲刺,Java“实战”问题三连,你碰到了哪个?
-
推荐学习全网首发!马士兵内部共享—1658页《Java面试突击核心讲》狂刷《Java权威面试指南(阿里版)》,冲击“金九银十”有望了Java“实战”问题三连Java“实战”面试题1:如果用mybati...
- 企业开发必备的6个Spring Cloud微服务开源项目
-
今天介绍六款比较热门的SpringCloud微服务项目,感兴趣的可以clone下来研究一下,相信对你学习微服务架构很有帮助。一、Cloud-Platform介绍Cloud-Platform是国内首个基...
- 系统架构设计方法论:系统演进的四重境界
-
在架构师面试中,设计能力的考察本质是验证候选人如何将混沌需求转化为可落地的技术方案。这不仅需要扎实的技术功底,更需要系统化的设计思维。以下四大步骤,既是架构设计的核心框架,也是技术决策的动态沙盘推演。...
- 跨浏览器共享Session信息方法总结
-
在不同浏览器之间共享Session信息需要克服浏览器间的隔离机制,常见解决方案如下:1.基于Token的跨浏览器传递实现方式:用户在主浏览器生成临时Token(如加密URL或二维码)。其他浏览器通过...
- 如何设计一套单点登录系统
-
一、介绍昨天介绍了API接口设计token鉴权方案,其实token鉴权最佳的实践场景就是在单点登录系统上。在企业发展初期,使用的后台管理系统还比较少,一个或者两个。以电商系统为例,在起步阶段,可能只有...
- SpringBoot实现单点登录几种方案
-
前言:单点登录(SingleSign-On,SSO)是企业应用系统中常见的用户认证方案,它允许用户使用一组凭证访问多个相关但独立的系统,无需重复登录。基于Cookie-Session的传统SSO方案...
- 零基础小白如何学爬虫技术?看一遍就会的详细教程!
-
你以为爬虫需要精通编程、算法、网络协议才能入门?错了。作为零基础的小白,你完全可以在3周内学会主流网站的数据抓取,核心秘诀就两点:拆分具体目标+倒推式学习。与其纠结Python语法、HTTP协议这...
- 探秘Java中的分布式锁:优雅地协调分布式系统
-
探秘Java中的分布式锁:优雅地协调分布式系统在分布式系统的架构中,数据一致性是一个永恒的挑战。当我们需要在多个节点之间协调某些操作时,分布式锁便成为了一种不可或缺的工具。它就像一把钥匙,能够控制对共...
- 一文读懂 Spring Boot 3 分布式事务解决方案
-
在当今复杂的业务架构中,分布式事务处理是关键难题之一。随着业务规模的不断扩张,系统架构从单体逐渐演进为分布式,这就要求开发人员能够熟练掌握高效的分布式事务解决方案,以保障数据的一致性和业务的稳定性。今...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (63)
- oracle批量插入数据 (62)
- oracle事务隔离级别 (53)
- oracle 空为0 (50)
- oracle主从同步 (55)
- oracle 乐观锁 (51)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)