OpenHarmony源码转换器—多线程特性转换

本文讨论了如何将多线程的 Java 代码转换为 OpenHarmony ArkTS 代码​

一、简介

Java 内存共享模型

以下示例伪代码和示意图展示了如何使用内存共享模型解决生产者消费者问题。

在这里插入图片描述

生产者消费者与共享内存间交互示意图

为了避免不同生产者或消费者同时访问一块共享内存的容器时产生的脏读,脏写现象,同一时间只能有一个生产者或消费者访问该容器,也就是不同生产者和消费者争夺使用容器的锁。当一个角色获取锁之后其他角色需要等待该角色释放锁之后才能重新尝试获取锁以访问该容器。

// 此段示例为伪代码仅作为逻辑示意,便于开发者理解使用内存共享模型和Actor模型的区别
BufferQueue {Queue queueMutex mutexadd(value) {// 尝试获取锁if (mutex.lock()) {queue.push(value)mutex.unlock()}}take() {// 尝试获取锁if (mutex.lock()) {if (queue.empty()) {return null}let res = queue.pop(value)mutex.unlock()return res}}
}// 构造一段全局共享的内存
let g_bufferQueue = new BufferQueue()Producer {run() {let value = random()// 跨线程访问bufferQueue对象g_bufferQueue.add(value)}
}Consumer {run() {// 跨线程访问bufferQueue对象let res = g_bufferQueue.take()if (res != null) {// 添加消费逻辑}}
}Main() {let consumer = new Consumer()let producer = new Producer()// 多线程执行生产任务for 0 in 10 :let thread = new Thread()thread.run(producer.run())consumer.run()
}

ArkTS Actor 模型

以下示例简单展示了如何使用基于Actor模型的TaskPool并发能力来解决生产者消费者问题。

Actor模型线程间通信示意图
在这里插入图片描述

Actor模型不同角色之间并不共享内存,生产者线程和UI线程都有自己独占的内存。生产者生产出结果后通过序列化通信将结果发送给UI线程,UI线程消费结果后再发送新的生产任务给生产者线程。

import taskpool from '@ohos.taskpool';
// 跨线程并发任务
@Concurrent
async function produce(): Promise<number>{// 添加生产相关逻辑console.log("producing...");return Math.random();
}class Consumer {public consume(value : number) {// 添加消费相关逻辑console.log("consuming value: " + value);}
}@Entry
@Component
struct Index {@State message: string = 'Hello World'build() {Row() {Column() {Text(this.message).fontSize(50).fontWeight(FontWeight.Bold)Button() {Text("start")}.onClick(() => {let produceTask: taskpool.Task = new taskpool.Task(produce);let consumer: Consumer = new Consumer();for (let index: number = 0; index < 10; index++) {// 执行生产异步并发任务taskpool.execute(produceTask).then((res : number) => {consumer.consume(res);}).catch((e : Error) => {console.error(e.message);})}}).width('20%').height('20%')}.width('100%')}.height('100%')}
}

Java 开发者仍然习惯于使用基于共享内存的并发模型,上手 actor 并发模型仍有一定的学习成本,但是借助 OpenHarmony源码转换器,Java 开发者可以无痛将代码迁移到 ArkTS,减轻工作负担。

二、方案对比

Java 开发者在处理并发问题时经常会碰到三个问题:可见性、原子性、有序性,好在都有解决方案,比如用锁来保证可见性,原子指令保证原子性,内存屏障保证有序性。正确使用时,并发粒度高,但出现问题时,很难调试复现。

ArkTS 并发模型不基于共享内存,因此并不会存在上述并发法问题,但并发粒度比较低。

OpenHarmony 实际上提供了两种线程机制:TaskPool、Worker。TaskPool 是对 Worker 的封装,开发者不需要去手动管理生命周期。Worker 线程机制最多开启 8 个线程。

TaskPool运作机制

TaskPool运作机制示意图
TaskPool支持开发者在主线程封装任务抛给任务队列,系统选择合适的工作线程,进行任务的分发及执行,再将结果返回给主线程。接口直观易用,支持任务的执行、取消。工作线程数量上限为4。

Worker运作机制

在这里插入图片描述
创建Worker的线程称为宿主线程(不一定是主线程,工作线程也支持创建Worker子线程),Worker自身的线程称为Worker子线程(或Actor线程、工作线程)。每个Worker子线程与宿主线程拥有独立的实例,包含基础设施、对象、代码段等。Worker子线程和宿主线程之间的通信是基于消息传递的,Worker通过序列化机制与宿主线程之间相互通信,完成命令及数据交互。

三、ArkTS 线程当前支持的通信方式

可序列化数据

对于可序列化的数据能够通过Structured Clone算法在线程间进行复制传输。支持的可序列化对象有限:除Symbol之外的基础类型、DateString、RegExp、Array、MapSet、Object (仅限简单对象,比如通过{}或者new Object创建,普通对象仅支持传递属性,不支持传递其原型及方法)、TypedArray。

可转移数据 ArrayBuffer

可转移对象(Transferable object)传输采用地址转移进行序列化,不需要内容拷贝,会将ArrayBuffer的所有权转移给接收该ArrayBuffer的线程,转移后该ArrayBuffer在发送它的线程中变为不可用,不允许再访问
let buffer = new ArrayBuffer(100)

可共享数据 SharedArrayBuffer

共享对象SharedArrayBuffer,拥有固定长度,可以存储任何类型的数据,包括数字、字符串等。

共享对象传输指SharedArrayBuffer支持在多线程之间传递,传递之后的SharedArrayBuffer对象和原始的SharedArrayBuffer对象可以指向同一块内存,进而达到内存共享的目的。

SharedArrayBuffer对象存储的数据在同时被修改时,需要通过原子操作保证其同步性,即下个操作开始之前务必需要等到上个操作已经结束。

let ia = new SharedArrayBuffer(1024): // 定义可共享对象,可以使用Atomics进行操作
ia[37] = 163;
console.log(ia[37]);  // Prints 163, the 38th prime
Atomics.store(ia, 37, 123);
while (Atomics.load(ia, 37) == 163);
console.log(ia[37]);  // Prints 123

四、实现难点

需要考虑到Java如下常用能力

  1. Java线程对共享内存的竞争,例如锁的使用
  2. Java线程之间的同步,例如生产与消费者模型
  3. Java线程之间的协同,例如线程的睡眠、唤醒。
  4. Java synchronize关键字的使用

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

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

相关文章

【小程序开发】解决 HBuilder X “本项目类型无法运行到小程序模拟器”

今天遇到一个奇怪的问题&#xff0c;从git导入的微信小程序项目准备运行到小程序模拟器时菜单没有展示出模拟器工具列表&#xff0c;而是展示了这么一个子菜单“本项目类型无法运行到小程序模拟器&#xff0c;点击看详情”。如下图&#xff1a; 点击是跳转到一个web链接。 我通…

【零基础入门TypeScript】判断条件和循环

目录 定环 无限循环 示例&#xff1a;while 与 do..while 中断语句 句法 流程图 例子 继续语句 句法 流程图 例子 输出 无限循环 语法&#xff1a;使用 for 循环的无限循环 示例&#xff1a;使用 for 循环的无限循环 语法&#xff1a;使用 while 循环进行无限循…

使用生成式AI查询大型BI表

在拥有大量表格形式数据的组织中&#xff0c;数据分析师的工作是通过提取、转换和围绕数据构建故事来理解这些数据。 分析师访问数据的主要工具是 SQL。 鉴于大型语言模型 (LLM) 令人印象深刻的功能&#xff0c;我们很自然地想知道人工智能是否可以帮助我们将信息需求转化为格式…

优雅地展示20w单细胞热图|非Doheatmap 超大数据集 细胞数太多

单细胞超大数据集的热图怎么画&#xff1f;昨天刚做完展示20万单细胞的热图要这么画吗&#xff1f; 今天就有人发消息问我为啥他画出来的热图有问题。 问题起源 昨天分享完 20万单细胞的热图要这么画吗&#xff1f;&#xff0c;就有人问为啥他的数据会出错。我们先来看下他的…

sql | sql 语句中的case when

通过case when 进行更细致的分类 ################################################## ####### 参考 ####### 如果没有添加case when 最终的sql 语句 就只是查询表中的name 而且添加 case when [age] > 18 then 1 else 0 end as [AgeType] 记就表示找表中的两个字段 一个是…

智能编程助手!华为云CodeArts Snap免费公测:基于盘古研发大模型

近日&#xff0c;华为云CodeArts Snap正式开启公测。 这是一款基于华为云研发大模型的智能化编程助手&#xff0c;旨在为开发者提供高效且智能的编程体验&#xff0c;提升研发人员的单兵作战能力。 该服务公测期间免费&#xff0c;不向用户收取任何费用&#xff0c;商用后&am…

在 UEFI+GPT 模式下,使用Symantec_Ghost_12.0.0.8006备份统信UOS+Windows10系统,固态硬盘也顺利

在 UEFIGPT 模式下&#xff0c;使用Symantec_Ghost_12.0.0.8006备份统信UOSWindows10系统&#xff0c;安装时双系统不说了。 ipxe系统下载好 某桃系统中pe64.wim下载好&#xff08;这个要注意&#xff0c;因为某桃系统pe较新适合新一些的电脑&#xff09;&#xff0c;替换掉p…

Java数据结构:1. 数据结构前置知识

文章目录 一、初识数据结构二、初识集合框架1. 什么是集合框架2. 集合框架的重要性3. 背后所涉及的数据结构以及算法 三、时间复杂度空间复杂度1. 算法效率2. 时间复杂度&#xff08;1&#xff09;概念&#xff08;2&#xff09;大O的渐进表示法&#xff08;3&#xff09;推导大…

python实现巴特沃斯低通滤波器——数字图像处理

原理&#xff1a; 巴特沃斯低通滤波器&#xff08;Butterworth Low-Pass Filter&#xff09;是图像处理中常用的一种频率域滤波器&#xff0c;它相较于理想低通滤波器提供了更平滑的过渡&#xff0c;以减少图像处理时引入的振铃效应。 设计原理&#xff1a; 巴特沃斯低通滤波…

高防ip适合防御网站和游戏类的攻击吗?

​  作为站长&#xff0c;要学会并承受得住网站外来攻击的压力&#xff0c;尤其是所属为 DDoS 攻击高发行业的网站类业务及游戏行业&#xff0c;是很容易被竞争对手或者一些伪黑客爱好者盯上的。 加上&#xff0c;有些站长并没有提前了解&#xff0c;就盲目进军了这两个行业&…

玩转贝启科技BQ3588C开源鸿蒙系统开发板 —— DevEco Studio下载与安装

一、下载DevEco Studio IDE开发工具 1. 登录鸿蒙官网 网址为&#xff1a; ​​​​​​​华为HarmonyOS智能终端操作系统官网 | 应用设备分布式开发者生态 页面如下&#xff1a; 2. 搜索“DevEco Studio IDE” 点击右上角的“请输入关键词”&#xff0c;在其中搜索“DevEc…

Hubery-个人项目经历记录

研究生期间很有幸的进入到了崔老师的组&#xff0c;从此也就进入到了分析人体生理信号的领域&#xff0c;充满挑战的同时也充满了乐趣。借着CSDN整理一下近几年来参与的项目&#xff0c;这里蕴含着我各种美好的回忆&#xff0c;也作为一个展示自己的平台吧。 开始之前&#xff…