结构化并发 ForkJoinPool StructuredTaskScope

Java 通过引入结构化并发 API 简化并发编程。结构化并发将在不同线程中运行的相关任务组视为单一工作单元,从而简化错误处理和取消操作、提高可靠性并增强可见性

结构化并发由 JEP 428 提出,并在 JDK 19 作为孵化API。它由 JEP 437 在 JDK 20 中重新孵化,并带有一个继承Scoped Values的版本更新 (JEP 429)

非结构化并发 ExecutorService

java.util.concurrent.ExecutorService API 是在 Java 5 中引入的,可帮助开发人员同时执行子任务

在下列代码中,对于两个无关联性的IO操作(如RPC、MySQL调用),通常使用线程池来并发执行findUser()fetchOrder()两个子任务

Response handle() throws ExecutionException, InterruptedException {Future<String>  user  = esvc.submit(() -> findUser());Future<Integer> order = esvc.submit(() -> fetchOrder());String theUser  = user.get();   // Join findUserint    theOrder = order.get();  // Join fetchOrderreturn new Response(theUser, theOrder);
}
  • 如果findUser()抛出异常,那么handle()在调用user.get()时会抛出异常,但是fetchOrder()将继续在自己的线程中运行。这称为线程泄漏
  • 如果handle()被中断,findUser()fetchOrder()将继续执行,会导致线程泄露
  • 如果findUser()需要很长时间执行,但fetchOrder()失败了,handle()主线程需要block在user.get()后才能感知异常

这不仅会导致产生错误的可能性更大,而且会使诊断和排除此类错误变得更加困难。例如,线程转储等可视化工具无法对任务之间的堆栈进行关联和追踪

ExecutorService 和 Future 允许这种非结构化使用,所以它们不会强制执行甚至跟踪任务和子任务之间的关系,即使这种关系很常见并且有用

结构化并发

结构化并发(Structured Concurrency)是一种并发编程模型,旨在简化和规范并发代码的编写和管理。它提供了一种结构化的方式来组织和控制并发任务的执行,以减少常见的并发编程问题,如资源泄漏、死锁和竞态条件等

结构化并发的核心思想是将并发任务组织为层次结构,并通过一些基本原则来管理它们的执行:

  1. 嵌套关系:并发任务可以嵌套在其他任务中,形成层次结构。父任务可以控制子任务的执行,并等待子任务完成。
  2. 继承关系:子任务的生命周期受父任务的控制。当父任务完成或取消时,它会自动取消所有的子任务。
  3. 顺序执行:任务按照顺序执行,一个任务的完成是下一个任务的前提条件。这样可以确保任务之间的依赖关系和顺序执行的一致性。
  4. 取消机制:任务可以被取消,取消操作会向下传递,取消所有嵌套的子任务。

结构化并发模型的一个重要特性是异常传播。当一个任务抛出异常时,它会被传播到父任务,并取消整个任务层次结构的执行。这有助于避免未处理的异常导致的问题,并提供了一种可靠的错误处理机制

StructuredTaskScopeForkJoinPool不同,ForkJoinPool是为计算密集型任务设置的,StructuredTaskScope默认使用虚线程,主要面向I/O密集型

计算密集型 ForkJoinPool

ForkJoinPool提供了一种结构化并发的机制,用于高效地执行并行任务,并在Java中广泛用于处理递归和分治算法等需要并行处理的场景。

ForkJoinPool适用于计算密集型任务

ForkJoinPool 是 Java 标准库中提供的一个用于并行执行任务的线程池实现。它基于工作窃取(work-stealing)算法,其中线程可以从其他线程的任务队列中窃取任务来执行

在 ForkJoinPool 中,任务被划分为更小的子任务,然后递归地执行这些子任务,直到达到某个终止条件。具体流程可见 parallelStream/ForkJoinPool 详解

IO密集型 StructuredTaskScope

StructuredTaskScope 允许开发人员将任务构建为一系列并发子任务,并将它们作为一个整体进行协调。子任务的成功的结果或异常由父任务聚合和处理

StructuredTaskScope适用于IO密集型任务

这是之前使用线程池的handle()示例,改为使用StructuredTaskScope而编写的

Response handle() throws ExecutionException, InterruptedException {try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {Supplier<String>  user  = scope.fork(() -> findUser());Supplier<Integer> order = scope.fork(() -> fetchOrder());scope.join()            // Join both subtasks.throwIfFailed();  // ... and propagate errors// Here, both subtasks have succeeded, so compose their resultsreturn new Response(user.get(), order.get());}
}

与原始示例相比,理解涉及的线程的生命周期很容易:在所有情况下,它们的生命周期都限定在一个词法范围内,即try-with-resources语句的主体部分。此外,使用StructuredTaskScope确保了许多有价值的属性:

  1. 错误处理与短路: 如果任务中的任一子任务失败,如果另一任务尚未完成,则将其取消。(由ShutdownOnFailure实现的关闭策略来管理)
  2. 取消传播: 如果运行handle()的线程在调用join()之前或期间被中断,当线程退出作用域时,两个子任务将自动取消
  3. 清晰度: 上述代码具有清晰的结构:设置子任务,等待它们完成或被取消,然后决定是成功还是失败
  4. 可见性: 线程转储(thread dump)清楚地显示了任务层次结构,其中运行子任务的线程显示为作用域的子级

StructuredTaskScope 是一个预览版 API,默认禁用。要启用需指定JVM参数--enable-preview


参考资料:

  1. JEP 453: Structured Concurrency (Preview)
  2. parallelStream/ForkJoinPool 详解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/218454.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在linux服上使用nginx+tomcat部署若依前后端分离版本(RuoYi-Vue)

一、先拉工程&#xff0c;地址&#xff1a;RuoYi-Vue: &#x1f389; 基于SpringBoot&#xff0c;Spring Security&#xff0c;JWT&#xff0c;Vue & Element 的前后端分离权限管理系统&#xff0c;同时提供了 Vue3 的版本 二、在window上用idea打开跑通&#xff0c;可参考…

vue 实现签字功能

1、安装&#xff1a;npm install vue-esign --save 2、main.js文件中全局引入&#xff1a; // 签字 import vueEsign from vue-esign Vue.use(vueEsign) 3、页面内容 <vue-esign ref"esign" :width"800" :height"300" :isCrop"isCro…

Leetcode—112.路径总和【简单】

2023每日刷题&#xff08;五十七&#xff09; Leetcode—112.路径总和 实现代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* …

LINUX:如何以树形结构显示文件目录结构

tree tree命令用于以树状图列出目录的内容。 第一步&#xff0c;先安装tree这个包 sudo apt-get install tree 第二步&#xff0c;在指定文件目录输入下面命令&#xff0c;7代表7级子目录 tree -L 7 第三步&#xff0c;效果图 第四步&#xff0c;拓展学习 颜色显示 tree -C显…

用Rust刷LeetCode之26 删除有序数组中的重复项

26. 删除排序数组中的重复项[1] 难度: 简单 老的描述: 新的描述: 注意是 排序数组,非严格递增排列,即已经是排好序的,只不过有重复元素 func removeDuplicates(nums []int) int { if len(nums) 0 { return 0 } i : 0 for j : 1; j < len(nums); j { …

[LLM]nanoGPT---训练一个写唐诗的GPT

karpathy/nanoGPT: The simplest, fastest repository for training/finetuning medium-sized GPTs. (github.com) 原有模型使用的莎士比亚的戏剧数据集, 如果需要一个写唐诗机器人&#xff0c;需要使用唐诗的文本数据&#xff0c; 一个不错的唐诗&#xff0c;宋词数据的下载…

C#多线程总结

目录 前言 一、异步线程 使用async和await关键字 基于委托实现 二、同步线程 三、Thread线程 开启线程 设置线程优先级 Thread拓展封装 四、ThreadPool线程池 常规使用 设置线程数 线程等待 Thread和ThreadPool比较 通过线程池做一些扩展&#xff08;定时器类&am…

Git篇---第七篇

系列文章目录 文章目录 系列文章目录前言一、如果分支是否已合并为master,你可以通过什么手段知道?二、 什么是SubGit?三、列举工作中常用的几个git命令?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文…

视频监控管理平台/智能监测/检测系统EasyCVR中HLS流无法播放的解决方案

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

【EI会议征稿】第三届电力系统与电力工程国际学术会议(PSPE 2024)

第三届电力系统与电力工程国际学术会议&#xff08;PSPE 2024&#xff09; 2024 3rd International Conference on Power System and Power Engineering(PSPE 2024) 第三届电力系统与电力工程国际学术会议&#xff08;PSPE 2024&#xff09;于2024年3月29-31日在中国三亚隆重召…

Python 反编译Il2Cpp APK

引入 https://github.com/Perfare/Il2CppDumper/ 实现 开源的Ii2Cpp Dumper可以帮助我们将So和globalmetadata.dat文件反编译出 Assembly-CSharp.dll 本博客教程可以帮助我们直接拖入APK反编译出来 调用方式 两种 第一种 拖入后回车运行 第二种 放入运行的根目录下 源码 i…

docker核心原理——unionfs、namespace、cgroup

docker 核心原理 docker的核心原理其实就是cgroupnamespaceunionfs 组合实现的隔离机制&#xff0c;资源控制等。 隔离机制 在容器进程启动之前重新挂载它的整个根⽬录“/”&#xff0c;⽤来为容器提供隔离后的执⾏环境⽂件系统通过Linux Namespace 创建隔离&#xff0c;决…

解决 php 连接mysql数据库时报错:Fatal error: Class ‘mysqli’ not found in问题【更新23.12.12】

在使用php对mysql进行连接的过程中&#xff0c;出现了Fatal error: Uncaught Error: Class "mysqli" not found in的问题 解决方案 这个错误通常表示您的PHP代码中缺少MySQL扩展或者没有启用MySQL扩展。 我们首先确认一下PHP环境中已经安装了MySQL扩展。检查一下自己…

谷歌评论更新完成--须知

谷歌完成了他们上次宣布的评论系统更新的推出。评论系统的未来更新将不再公布&#xff0c;因为为评论系统提供支持的算法将定期和持续更新。 评论系统 谷歌的评论系统是一个系统&#xff0c;用作一组算法的一部分&#xff0c;这些算法共同产生搜索结果。 评论系统在对评论相…

骨传导耳机十大品牌排行榜,骨传导耳机品牌排名哪个好

骨传导蓝牙耳机的使用越来越广泛&#xff0c;无论是在户外运动还是在办公室工作&#xff0c;它都能为你带来自由的音乐体验。在本文中&#xff0c;我们将为你介绍十款TOP级骨传导蓝牙耳机&#xff0c;这些品牌在市场上拥有良好的口碑和广泛的使用者。通过本下面的选购指南&…

Filter的url-pattern、Filter的生命周期以及FilterConfig和一个拦截访问的小案例

1.url-pattern&#xff1a;Filter的拦截路径&#xff0c;即浏览器在请求什么位置的资源时&#xff0c;过滤器会进行拦截 2.精准匹配<url-pattern>/a.jsp</url-pattern>对应的请求地址&#xff1a;http://ip[域名]:port/工程路径/a.jsp会拦截 3.目录匹配<url-p…

CanEasy多场景应用,让汽车总线测试更简单

来源&#xff1a;虹科汽车电子 虹科分享 | CanEasy多场景应用&#xff0c;让汽车总线测试更简单 原文链接&#xff1a;https://mp.weixin.qq.com/s/ojic4xfVTLbxXcKlJMGQZw 欢迎关注虹科&#xff0c;为您提供最新资讯&#xff01; 导读 CanEasy是一个基于Windows的总线工具&…

SpringBoot项目静态资源默认访问目录

SpringBoot项目&#xff1a;静态资源默认访问目录 参考博客&#xff1a;https://blog.csdn.net/weixin_43808717/article/details/118281904

基于itextpdf的java读取和更新pdf表单域字段值功能

基于itextpdf的java读取和更新pdf表单域字段值功能 执行结果为&#xff1a; Hello World! keytopmostSubform[0].Page1[0].qhjc[0] keytopmostSubform[0].Page1[0].qhmc[0] keytopmostSubform[0].Page1[0].cqzh[0] keytopmostSubform[0].Page1[0].fm_year[0] keytopmostSubf…

wx.chooseLocation 用户选择地理位置的api使用方式,(uniapp)

框架&#xff1a;uniapp &#xff0c;开发微信小程序&#xff0c; 遇到的场景&#xff1a;需要用户选择地理位置 首先贴api官方文档 开发前注意事项&#xff1a;网址 调用这个api前需要在manifest.json里面配置声明该接口&#xff08;必须&#xff09; "permission&q…