写点什么

JEP 481:作用域值 API 的第 3 个预览版随 JDK 23 发布,带来关键增强

  • 2024-08-12
    北京
  • 本文字数:1628 字

    阅读完需:约 5 分钟

JEP 481:作用域值API的第3个预览版随JDK 23发布,带来关键增强

JEP 481(作用域值第 3 个预览版)——之前称为范围局部变量(孵化)——提供了第三次预览。该版本只有一个变化,旨在从之前的一轮孵化和两轮预览之外获得额外的经验和反馈:随 JDK 22 交付的 JEP 464(作用域值第 2 个预览版)、随 JDK 21 交付的 JEP 446(作用域值预览版)以及随 JDK 20 交付的 JEP 429(作用域值孵化)。该特性支持在线程内部和线程之间共享不可变数据。


在 JDK 23 中重新预览的作用域值 API 修改了ScopedValue.callWhere方法。现在,这个方法的操作参数是一个函数式接口。它允许 Java 编译器推断是否可能抛出检查异常。因此,ScopedValue.getWhere这个方法就不再需要了,而且已经删除。在频繁共享数据的场景中,这会使代码更简洁,而且性能更好。


作用域值使方法能够与其调用者和子线程共享不可变数据。与线程局部变量相比,这可以简化数据流的管理和推断。而且,它们的空间和时间成本更低,特别是在与虚拟线程(JEP 444)和结构化并发(JEP 480)结合使用时。


不过,Java 1.2 中引入的线程局部变量一直是一个简化同一线程内方法间数据共享的传统方法。尽管已经使用了很长时间,但它还是有一些缺点。一个主要的问题是它们毫无约束的可变性,任何代码都可以随时更改线程局部变量的值,这可能导致潜在的不一致。另一个缺点是它们的寿命不受限制;如果开发人员忘记调用remove方法,值的保存时长可能会超过所需的时长,而这通常会导致内存泄漏。此外,跨线程继承线程局部变量会显著增加开销,因为每个子线程都必须为先前在父线程中写入的每个线程局部变量分配存储空间,这会对性能产生负面影响。


作用域值解决了这个问题,它确保数据是不可变的,并且只能在定义好的作用域中访问。这增强了安全性和性能。


为了说明作用域值的好处,考虑下这样一个 Web 框架,它的上下文需要在不同的方法之间共享,而又不需要显式地将其作为参数传递。使用线程局部变量,该框架可能是这样的:


class Framework {
private final static ThreadLocal<FrameworkContext> CONTEXT = new ThreadLocal<>();
void serve(Request request, Response response) { var context = createContext(request); CONTEXT.set(context); Application.handle(request, response); }
public PersistedObject readKey(String key) { var context = CONTEXT.get(); var db = getDBConnection(context); return db.readKey(key); }}
复制代码


使用作用域值,其实现会变得更加简洁、高效:


class Framework {
private final static ScopedValue<FrameworkContext> CONTEXT = ScopedValue.newInstance();
void serve(Request request, Response response) { var context = createContext(request); ScopedValue.runWhere(CONTEXT, context, () -> Application.handle(request, response)); }
public PersistedObject readKey(String key) { var context = CONTEXT.get(); var db = getDBConnection(context); return db.readKey(key); }}
复制代码


使用线程局部变量,当框架调用用户代码以及当用户代码回调框架方法时,不需要将FrameworkContext作为方法的参数进行传递。线程局部变量是作为一个隐藏的方法参数:线程调用Framework.serve中的CONTEXT.set。然后,Framework.readKey中的CONTEXT.get自动就可以看到CONTEXT的本地副本。实际上,ThreadLocal字段充当了一个键,用于查找当前线程的FrameworkContext值。另一方面,使用作用域值简化了这个过程。它消除了可变状态,并且确保上下文只能在runWhere方法定义好的范围内访问,从而提供了一种更健壮且性能更好的方法。总之,作用域值 API 显著增强了 Java 中跨方法和线程共享数据的方式,促进了更好的编码实践,并提高了应用程序的性能。它非常符合现代并发模型,特别是当虚拟线程出现之后,它为开发人员处理高并发应用程序提供了一个重要的选项。


原文链接:

https://www.infoq.com/news/2024/07/jep-481-enhanced-scoped-values/

2024-08-12 08:005873

评论

发布
暂无评论
发现更多内容

使用无代码构建客户门户

间隔

内网穿透你真的了解吗?

C++后台开发

网络安全 NAT Linux服务器开发 内网 网络穿透

多年缓慢成长,近3年野蛮狂飙,谁是这个赛道的王者?

ToB行业头条

模块四课后作业 - 设计千万级学生管理系统的考试试卷存储方案

闲人Eric

架构实战营

小游戏开发投放平台及分成政策盘点

Onegun

小游戏 小游戏开发

华为云桌面,助力企业数字化转型

爱尚科技

PHP转Go之后,我又开始研究机器学习和自动驾驶了。

王中阳Go

自动驾驶 Apollo

32篇年度最佳AI论文;Python编译器Codon开源;ChatGPT的前世今生

OneFlow

人工智能 深度学习 大模型

华为云桌面解决方案,打造安全高效办公新体验

科技怪授

云桌面

小程序游戏的3大分发平台

FinFish

小程序 小游戏 小游戏运营

SpringMVC还是Spring WebFlux?谁是下一代的Java程序员技术栈?

程序员小毕

Java spring 程序员 后端 springmvc

天翼云斩获2022全球分布式云大会两项大奖

天翼云开发者社区

案例丨多元业态管理服务厂商如何走通数字化转型之路

优秀

数字化转型 数字化管理

软件测试面试真题 | 什么是 Redis ? Redis缓存应用场景有哪些?

测试人

redis 软件测试 自动化测试 测试开发

语音生成领域模型又填一名猛将

felix

深度学习 语音合成 TTS

当云原生网关遇上图数据库,NebulaGraph 的 APISIX 最佳实践

NebulaGraph

图数据库 API网关

【经验】硬件工程师与PCB槽孔斗智斗勇的故事

华秋PCB

工具 PCB PCB设计 槽孔

基于Seata探寻分布式事务的实现方案

京东科技开发者

大数据 分布式事务 微服务架构 关系型数据库 seata

软件测试面试真题 | 需求评审中从几个方面发现问题

测试人

软件测试 面试题 自动化测试 测试开发 需求评审

架构实战营第 10 期 - 模块三作业:外包学生管理系统详细架构设计文档

kaizen

「架构实战营」

新茶饮 200+ 门店优化库存成本,需要几个数据分析师?

Kyligence

数据分析 指标中台

Docker daemon configuration overview(Docker 守护进程配置概览)

独钓寒江

【从零开始学爬虫】采集全国高校导师数据

前嗅大数据

数据采集 爬虫教程 爬虫入门

MySQL分库分表,可能真的要退出历史舞台了!

Java永远的神

MySQL 程序员 后端 架构师 分布分表

华为云桌面,让企业随时随地开启云上办公

爱尚科技

外包学生管理系统架构文档

白杨

2022年中国第三方输入法发展分析

易观分析

报告 输入法 语音输入

数字先锋| 药品信息何处有?尽在标识编码处

天翼云开发者社区

【观察】融云百幄:为政企数智办公按下“快进键”

融云 RongCloud

融云 数智化 政企 百幄

融云任杰:激活组织生命力 让听见炮火的人做决策 | TGO专访

融云 RongCloud

专访 程序员‘

5分钟搞懂Jenkins分布式架构

俞凡

架构 DevOps cicd 最佳实践

JEP 481:作用域值API的第3个预览版随JDK 23发布,带来关键增强_编程语言_A N M Bazlur Rahman_InfoQ精选文章