网站首页 > 技术文章 正文
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 性能的数量级提升可能会改变未来几年的格局。
- 上一篇: java 最近有什么新的发展(2025年6月)?
- 下一篇: SQL_约束
猜你喜欢
- 2025-08-05 java 最近有什么新的发展(2025年6月)?
- 2025-08-05 C#并发编程经典实例,中文版高清PDF资源
- 2025-08-05 并发编程:乱序执行的那些事儿五分钟给你整明白
- 2024-11-01 Oracle优化Hints功能并行parallel(二)
- 2024-11-01 PostgreSQL开发与实战(7.3)多版本并发控制3
- 2024-11-01 GitHub大神手打笔记:MySQL的多版本并发控制
- 2024-11-01 并发类的覆盖驱动测试代码生成 植被覆盖类型代码1112指的是
- 2024-11-01 MySQL的多版本并发控制(MVCC) mysql多版本多实例部署
- 2024-11-01 多版本并发控制(MVCC)与一致性读(二)
- 2024-11-01 SQLite学习笔记(二) sql学习笔记
你 发表评论:
欢迎- 648℃几个Oracle空值处理函数 oracle处理null值的函数
- 639℃Oracle分析函数之Lag和Lead()使用
- 637℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 631℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 626℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 612℃【数据统计分析】详解Oracle分组函数之CUBE
- 607℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 589℃Oracle有哪些常见的函数? oracle中常用的函数
- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端路由 (61)
- 前端数组 (73)
- 前端js面试题 (50)
- 前端定时器 (59)
- Oracle RAC (76)
- oracle恢复 (77)
- oracle 删除表 (52)
- oracle 用户名 (80)
- oracle 工具 (55)
- oracle 内存 (55)
- oracle 导出表 (62)
- oracle约束 (54)
- oracle 中文 (51)
- oracle链接 (54)
- oracle的函数 (58)
- oracle面试 (55)
- 前端调试 (52)
本文暂时没有评论,来添加一个吧(●'◡'●)