写点什么

JEP 428:结构化并发,简化 Java 多线程编程

作者:A N M Bazlur Rahman

  • 2022-06-17
  • 本文字数:2284 字

    阅读完需:约 7 分钟

JEP 428:结构化并发,简化Java多线程编程

JEP 428,即结构化并发(孵化器阶段),已经从 Proposed 状态进入到 Target 状态。在 Project Loom 的框架下,这个 JEP 提议引入一个库,将在不同线程中运行的多个任务视为原子操作,以此来简化多线程编程。它可以简化错误处理和取消操作,提高可靠性,并增强可观察性。这个 API 仍然在孵化当中。


开发人员可以使用 StructuredTaskScope 类来组织他们的并发代码,这个类将把一组子任务视为一个单元。子任务通过单独的线程创建,然后连接成一个单元,也可以作为一个单元进行取消。子任务的异常或执行结果将由父任务进行聚合和处理。让我们来看一个例子:


Response handle() throws ExecutionException, InterruptedException {   try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {       Future<String> user = scope.fork(() -> findUser());       Future<Integer> order = scope.fork(() -> fetchOrder());
scope.join(); // 连接 scope.throwIfFailed(); // 抛出错误
// 聚合结果 return new Response(user.resultNow(), order.resultNow()); }}
复制代码


上面的 handle()方法表示服务器应用程序的一个任务。它创建了两个子任务来处理传入的请求。与 ExecutorService.submit()一样,StructuredTaskScope.fork()接受 Callable 作为参数,并返回 Future。与 ExecutorService 不同的是,返回的 Future 不是通过 Future.get()来连接的。这个 API 运行在 JEP 425 之上——虚拟线程(预览阶段),发布目标也为 JDK 19。


上面的例子使用了 StructuredTaskScope API,如果要在 JDK 19 上运行它们,必须添加 jdk.incubator.concurrent 模块,同时要启用预览功能来使用虚拟线程。


使用下面的命令编译上述代码:


javac --release 19 --enable-preview --add-modules jdk.incubator.concurrent Main.java
复制代码


运行程序也需要提供相同的标志:


java --enable-preview --add-modules jdk.incubator.concurrent Main
复制代码


不过,我们也可以使用源代码启动器直接运行它,命令应该是这样的:


java --source 19 --enable-preview --add-modules jdk.incubator.concurrent Main.java
复制代码


jshell 也是可用的,但也需要启用预览功能:


jshell --enable-preview --add-modules jdk.incubator.concurrent
复制代码


结构化并发带来了很多好处。它为调用者方法及其子任务创建了一种父子关系。例如,在上面的例子中,handle()任务是父,它的子任务 findUser()和 fetchOrder()是子。结果,整个代码块变成了原子代码。它通过线程转储中的任务层次结构来提供可观察性。它还可以在错误处理中实现短路,如果其中一个子任务失败,其他未完成的任务将被取消。如果父任务的线程在 join()调用之前或期间被中断,两个分支将在作用域退出时自动取消。这让并发代码的结构变得更加清晰,开发人员现在可以推理和跟踪代码,就好像它们是在单线程环境中运行。


早期的程序流程普遍使用 GOTO 语句来控制,代码十分混乱,这种意大利面条式的代码难以阅读和调试。随着编程范式的成熟,编程社区认识到 GOTO 语句是有害的。1969 年,以《计算机编程的艺术》一书而闻名的计算机科学家 Donald Knuth 表示,没有 GOTO 也可以高效地编写程序。后来,结构化编程的出现解决了所有这些缺点。看一下下面的例子:


Response handle() throws IOException {   String theUser = findUser();   int theOrder = fetchOrder();   return new Response(theUser, theOrder);}
复制代码


上面的代码是结构化代码的一个例子。在单线程环境中,handle()方法被调用时将按顺序执行。fetchOrder()方法不会在 findUser()方法之前启动。如果 findUser()方法失败,下面的方法根本不会启动,handle()方法将隐式失败,这反过来确保了原子操作成功或不成功。它提供了 handle()方法及其子方法之间的父子关系,遵循错误传播的规则,并在运行时提供调用堆栈信息。


然而,这种方法和推理并不适用于我们当前的线程编程模型。例如,如果我们想用 ExecutorService 改写上述的代码,就像这样:


Response handle() throws ExecutionException, InterruptedException {   Future<String>  user  = executorService.submit(() -> findUser());   Future<Integer> order = executorService.submit(() -> fetchOrder());   String theUser  = user.get();   // 连接findUser   int theOrder = order.get();  // 连接fetchOrder   return new Response(theUser, theOrder);}
复制代码


ExecutorService 中的子任务独立运行,可能成功或失败。即使父任务被中断,中断也不会被传播到子任务,因此会造成泄漏。它没有了父关系。由于父任务和子任务将出现在线程转储不相关的线程调用堆栈上,因此调试也变得困难。尽管代码看起来具有逻辑结构,但这种结构只停留在开发人员的头脑中,而不是在执行过程中。所以,它们是非结构化的并发代码。


通过观察非结构化并发代码存在的这些问题,Martin Sústrik 在他的博文中创造了“结构化并发”这个术语,然后 Nathaniel J. Smith 在他关于结构化并发的文章中推广了这个术语。关于结构化并发,Oracle 技术咨询成员、Loom 项目负责人 Ron Pressler 在 InfoQ 的一个播客中说道:


结构化的意思是,如果你生成了什么东西,你必须等待并连接它。这里的“结构”与它在结构化编程中的含义相似。代码的块结构反映了程序的运行时行为。因此,就像结构化编程提供了顺序控制流保证,结构化并发也为并发提供了同样的保证。有兴趣深入了解结构化并发及其背景故事的开发者可以收听 InfoQ 的博客,或者观看 Ron Pressler 在YouTube上的分享以及Inside Java的文章。


原文链接

JEP 428: Structured Concurrency to Simplify Java Multithreaded Programming

2022-06-17 08:085617

评论

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

解锁未来财富密码:AI自动化副业创收班——终身财富加速器

测吧(北京)科技有限公司

测试

花第1小时成tidb专家--云上资源特别,贵公司让我省钱ap篇

TiDB 社区干货传送门

8.x 实践

花2小时成tidb专家--云上资源特别贵kv业务的节省

TiDB 社区干货传送门

8.x 实践

解锁未来财富密码:AI自动化副业创收班-终身财富加速器

测试人

人工智能 软件测试

解锁未来财富密码:AI自动化副业创收班——终身财富加速器

霍格沃兹测试开发学社

INAIR 发布新款 AR 空间计算机 INAIR 2 ,定位移动大屏生产力工具

新消费日报

巴黎同款,六自由度技术还原赛场决定性瞬间!

快手技术

视频 渲染

TiKV 事务介绍

TiDB 社区干货传送门

TiKV 源码解读

记录一起非数据热点引起的TiKV负载不均衡

TiDB 社区干货传送门

故障排查/诊断

解决tiup‘ssh: unable to authenticate’报错

TiDB 社区干货传送门

集群管理 管理与运维 故障排查/诊断 扩/缩容

为什么前端越来越难学?聊聊 JavaScript 框架

秃头小帅oi

亚信安慧AntDB数据库入选《2024年中国信创产业发展白皮书》,并获“中国信创数据库卓越品牌”奖

亚信AntDB数据库

AntDB 企业号 8 月 PK 榜

AI2021矢量图形软件:Illustrator 2021 Win/Mac 直装版

你的猪会飞吗

mac软件下载 AI2021软件下载

与高质量发展同行,华大北斗获评“广东知名品牌”

江湖老铁

从原理到实践,GraphRAG 如何提升 LLM 的摘要总结能力?

可信AI进展

GC异常导致空间不释放,如何通过 tikv-ctl recover-mvcc 修复

TiDB 社区干货传送门

故障排查/诊断

ERP需要MES的五个理由

万界星空科技

系统集成 ERP 生产管理系统 mes 万界星空科技

思迈特发布全新AI应用,Smartbi AIChat白泽来了!

ToB行业头条

45 天备考!一次通过软考高级架构师考试的秘诀!

可信AI进展

人工智能

OpenTiny HUICharts开源发布,带你了解一个简单、易上手的图表组件库

华为云开发者联盟

前端 组件库 OpenTiny 企业号 8 月 PK 榜 2024企业号8月pk

操作ArkTS页面跳转及路由相关心得

OpenTiny社区

开源 前端 OpenTiny ArkTS

堡垒机高可用主备模式部署定义以及优势讲解!

行云管家

等保 堡垒机 堡垒机品牌

TiDB 执行计划代价模型分析

TiDB 社区干货传送门

性能调优 TiDB 底层架构

包头等保测评中心电话是多少?在哪里?

行云管家

等保测评 包头 等保测评机构

GPT-4o新版本突然上线!更强更便宜!阿里云推出首个域名AI应用!|AI日报

可信AI进展

人工智能

一年同行:我的TiDB社区之旅 

TiDB 社区干货传送门

人物访谈

万界星空科技低代码云MES系统

万界星空科技

低代码平台 mes 云mes 万界星空科技 低代码云MES

JEP 428:结构化并发,简化Java多线程编程_语言 & 开发_InfoQ精选文章