ArtTS语言基础类库内容的学习(2.10.1)

上篇回顾: ArkTS开发系列之Web组件的学习(2.9)

本篇内容:ArtTS语言基础类库-异步同步并发内容的学习(2.10.1)

一、知识储备

1. 异常并发

Promise和Async/await提供异步并发能力,是标准的JS异步语法

  • Promise是一种用于处理异常操作的对象, 可以将异步操作转换为类似于同步操作的风格,以方便代码编写和维护。
  • 分别有pending(进行中)、fulfilled(已完成)和rejected(已拒绝)。
  • 下面是个例子
  promiseFunction() {const promise = new Promise((resolve, reject) => {setTimeout(() => {//通过 setTimeout来模拟一个异步操作   此时处于进行中状态(pending)const randomNumber = Math.random();if (randomNumber > 0.5) {//随机数大于0.5, 则正常返回,否则返回异常信息resolve(randomNumber)} else {reject(new Error('Random number is too small'))}}, 1000)})promise.then(result => {// fulfilled 成功完成回调状态this.tips = "异步结果:" + result;promptAction.showToast({ message: this.tips });}).catch(err => {// rejected 已被拒绝的回调状态this.tips = '异步结果:' + err.messagepromptAction.showToast({ message: this.tips });})}

async/await是一种用于处理异步操作的Promise语法糖, 通过使用async关键字来声明一个函数为异步函数, 并使用await关键字等promise的成功或拒绝回调。以同步的方式来编写异步代码,使代码更为简洁、易读。

  async asyncPromiseFunction() {const result = await new Promise((resolve, reject) => {setTimeout(() => {resolve('success')}, 1000)})console.log('结果:' + result)this.tips = "异步结果:" + result;promptAction.showToast({ message: this.tips });}

2.1 多线程并发

常见的并发模型分为基于内存共享并发模型和基于消息通信并发模型两种。
Actor并发模型作为基于消息通信并发模型的典型代表,不需要开发者去面对锁带来的一系列复杂偶发的问题,同时并发度也相对较高。
由于Actor模型的内存隔离特性,所以需要进行跨线程的数据序列化传输。

  • 数据传输对象分为普通对象、可转移对象、可共享对象、Native绑定对象四种
  • 普通对象采用结构化克隆算法(Structured Clone)进行序列化传输,此算法可以通过递归的方式拷贝传输对象,相较所支持的对象类型更加丰富。
    • 可传输对象包括除Symbol之外的基础类型、Date、String、RegExp、Array、Map、Set、ArrayBuffer、TypedArray、Object(仅限简单对象,比如通过"{}"或“new object”创建。仅支持传递属性、不支持传递其原型及方法)
  • 可转移对象采用地址转移进行序列化传输,不需要内容拷贝,会将ArrayBuffer的所有权转移给接收该ArrayBuffer的线程,转移后该ArrayBuffer在发送它的线程中变为不可用, 不允许再访问。
    • 定义可转移对象
    let buffer = new ArrayBuffer(100);
    
  • 可共享对象指支持在多线程之间传递SharedArrayBuffer对象。传递之后的SharedArrayBuffer对象和原始的可以指向同一块内存,进而达到内存共享的目的。
    • SharedArrayBuffer对象存储的数据在同时被修改时,需要通过原子操作保证其同步性,即下个操作开始之前,务必需要等到上个操作已经结束。
    • 定义可共享对象
    let sharedBuffer = new SharedArrayBuffer(1024);
    
  • Native绑定对象(Native Binding Object),是系统所提供的对象,该对象与底层系统功能进行绑定,提供直接访问底层系统功能的能力。
    • 当前支持序列化传输的Native绑定对象主要包含:ContextRemoteObject.
    • Context对象包含应用程序组件的上下文信息,并提供了一种访问系统服务和资源的方式,方便开发者开发的应用与系统进行交互。
    • RemoteObject对象的主要作用是实现远程通信的功能,它允许在不同的进程间传递对象的引用 。使得不同进程之间可以共享对象的状态和方法,服务提供者必须继承此类。

2.2 TaskPool(任务池)和Worker

实现特点及使用场景直观对比

实现TaskPoolWorker差异点
内存模型线程间隔离,内存不共享线程间隔离,内存不共享相同
参数传递机制采用标准的结构化克隆算法(Structured Clone)进行序列化、反序列化,完成参数传递。支持ArrayBuffer转移和SharedArrayBuffer共享。采用标准的结构化克隆算法(Structured Clone)进行序列化、反序列化,完成参数传递。支持ArrayBuffer转移和SharedArrayBuffer共享。相同
参数传递直接传递,无需封闭,默认进行transfer。消息对象唯一参数,需要自己封装。是否需要封装不同
返回值异步调用后默认返回主动发送消息,需要在onMessage解析赋值接收返回值方式不同
生命周期TaskPool自动管理生命周期,无需关心任务负载高低问题开发者自动管理Worker的数量及生命周期是否需要开发者管理不同
任务池个数上限自动管理,无需配置同个进程下,最多支持同时开启8个Worker线程开启线程个数不同
任务执行时长上限无限制无限制相同
设备任务的优先级不支持不支持相同
执行任务的取消支持取消任务队列中等待的任务不支持Worker不支持取消任务
适用场景需要频繁取消的任务,例如图库大图浏览场景,为提升体验,会同时缓存当前图片左右侧各2张图片,适合使用TaskPool;大师或者调度点分散的任务,例如大型应用的多个模块包含多个耗时任务,不方便使用8个Worker去做负载管理。推荐使用TaskPool有关联的一系列同步任务,例如每次创建、使用不同句柄,且句柄需要永久保存,保证使用该句柄操作,需要使用Worker。
  • TaskPool 注意事项
    • 实现任务的函数需要使用装饰器@Concurrent标注,且仅支持在.ets文件中使用
    • 实现任务的函数入参,需满足序列化支持的类型,
    • 由于线程中上下文对象是不同的,因此TaskPool工作线程中只能使用线程安全的库。不能做ui相关操作,
    • 序列化传输的数据量大小限制为16MB
  • Worker 注意事项
    • 创建Worker时,传入的Worker.ts路径在不同版本有不同的规则
    • Worker创建后需要手动管理生命周期,且同进程中最多同时运行的Worker子线程数量为8个
    • Ability类型的Modul支持使用Worker,Library类型的Module不支持使用Worker
    • 创建Worker不支持使用其他Module的Wroker.ts文件,即不支持跨模块调用Worker
    • 由于不同线程中上下文对象是不同的,因此Worker线程只能使用线程安全的库,不能做ui相关操作。
    • 序列化传输的数据量大小限制为16MB
  • 文件路径注意事项
    • 创建Worker时,需要传入Worker的路径,Worker文件存放位置默认路径为Worker文件所在目录与pages目录同级
      //导入模块
      import worker from '@ohos.worker';//APi8及之前
      const worker = new worker.Worker(scriptUrl);//APi 9及之后
      const worker = new worker.ThreadWorker(scriptUrl);
      //写法一
      const worker = new worker.ThreadWorker('entry/ets/workers/MyWorker.ts', {name: "name"});
      //写法二
      const worker = new worker.ThreadWorker('@bundle:com.aji.study/entry/ets/workers/worker')
      

2.3 @Concurrent装饰器

使用TaskPool时,执行的头发函数需要使用该装饰器修饰,否则无法通过相关校验。
注意

  • 仅支持在Stage模型且module的compileMode为esmodule的project中使用taskpool api。确认module的compileMode方法:查看当前module的build-profile.json5,在buildOption中补充"compileMode": “esmodule”。
    @Concurrent
    function add(numa: number, numb: number): number { //声明一个加法函数return numa + numb;
    }async function calcTotal(): Promise<void> {try {let task: taskpool.Task = new taskpool.Task(add, 1, 2) //创建一个任务let count = await taskpool.execute(task);console.error("taskpool result is: " + count) //任务池执行任务} catch (err) {console.error("taskpool err is " + err.message);}
    }
    

二、效果一览

在这里插入图片描述

三、源码剖析

import promptAction from '@ohos.promptAction';
import fs from '@ohos.file.fs';
import common from '@ohos.app.ability.common';
import taskpool from '@ohos.taskpool';
import Handle from './Handle';
import worker from '@ohos.worker';function promiseFunction() {const promise = new Promise((resolve, reject) => {setTimeout(() => { //通过 setTimeout来模拟一个异步操作   此时处于进行中状态(pending)const randomNumber = Math.random();if (randomNumber > 0.5) { //随机数大于0.5, 则正常返回,否则返回异常信息resolve(randomNumber)} else {reject(new Error('Random number is too small'))}}, 1000)})promise.then(result => { // fulfilled 成功完成回调状态let tips = "异步结果:" + result;promptAction.showToast({ message: tips });}).catch(err => { // rejected 已被拒绝的回调状态let tips = '异步结果:' + err.messagepromptAction.showToast({ message: tips });})
}async function asyncPromiseFunction() {const result = await new Promise((resolve, reject) => {setTimeout(() => {resolve('success')}, 1000)})console.log('结果:' + result)let tips = "异步结果:" + result;promptAction.showToast({ message: tips });
}async function write(data: string, file: fs.File): Promise<void> { //定义的I/O任务逻辑fs.write(file.fd, data).then((writeLen: number) => {console.info('write data length is : ' + writeLen); //写入的文本长度}).catch(err => {console.error(`failed code: ${err.code}, msg: ${err.message}`) //异常捕获 并输出日志})
}async function writeFunction(): Promise<void> {let context = getContext() as common.UIAbilityContext;let filePath: string = context.filesDir + "/test.txt";let file: fs.File = await fs.open(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)write('我要学鸿蒙', file).then(() => {console.info("write success")fs.close(file);}).catch(err => {console.error(`write failed code: ${err.code}, msg: ${err.message}`) //异常捕获 并输出日志fs.close(file);})
}@Concurrent
function add(numa: number, numb: number): number { //声明一个加法函数return numa + numb;
}async function calcTotal(): Promise<void> {try {let task: taskpool.Task = new taskpool.Task(add, 1, 2) //创建一个任务let count = await taskpool.execute(task);console.error("taskpool result is: " + count) //任务池执行任务} catch (err) {console.error("taskpool err is " + err.message);}
}@Concurrent //步骤1 定义并发函数,内部调用同步方法
function age(num: number): boolean {Handle.syncSet(num);return true;
}async function asyncGet() { //步骤2 创建任务并执行let task = new taskpool.Task(age, 3);let result = await taskpool.execute(task);console.error(`age is : ${result}`)
}@Entry
@Component
struct Index { //异步和并发@State tips: string = '异步结果'build() {Column() {Button('Promise异步').onClick(() => {promiseFunction();}).margin(20)Button('async异步').onClick(() => {asyncPromiseFunction();}).margin(20)Button('I/O').onClick(() => {writeFunction();}).margin(20)Button('年龄').onClick(() => {calcTotal();asyncGet(); //执行并发操作}).margin(20)Button('worker').onClick(() => {// let w = new worker.ThreadWorker('@bundle:com.aji.first/entry/ets/workers/MyWorker');let w = new worker.ThreadWorker('entry/ets/workers/MyWorker.ts');w.onmessage = function (msg) {console.error('msg: ' + JSON.stringify(msg))}w.onerror = function (err) {console.error("msg err:" + JSON.stringify(err))}w.postMessage({ 'type': 0, 'age': 19 })w.postMessage({ 'type': 1 })setTimeout(() => {w.terminate();console.error('msg destroy')}, 1000)})}.width('100%').height('100%')}
}
import worker, { ThreadWorkerGlobalScope } from '@ohos.worker';
import Handle from '../pages/base/Handle';var workerPort: ThreadWorkerGlobalScope = worker.workerPort;var handler = new Handle();workerPort.onmessage = function (msg) {console.error('msg workerPort: ' + JSON.stringify(msg))switch (msg.data.type) {case 0:Handle.syncSet(msg.data.age);workerPort.postMessage('success set')break;case 1:Handle.syncGet();workerPort.postMessage('success get')break;}
}workerPort.onerror = function onErr(err) {}
export default class Handle {static age: number;static instance: Handle = new Handle();constructor() {}static getInstance() {return this.instance;}static syncGet(): number {return this.age;}static syncSet(num: number) {this.age = num;return;}
}

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

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

相关文章

Scala的Actor模型:并发编程的革命性抽象 摘要

标题&#xff1a;Scala的Actor模型&#xff1a;并发编程的革命性抽象 摘要 Scala语言以其强大的函数式编程特性和并发模型而闻名。Actor模型作为Scala并发编程的核心&#xff0c;提供了一种高效、可靠的并行处理方式。本文将深入探讨Scala的Actor模型&#xff0c;包括其设计理…

亿发微商城:从社交流量到生意增量,拓客+变现双收益

亿发微商城提供私域经营必备的系统 、服务和技术支持等全套解决方案。省去开发成本&#xff0c;还原品牌调性&#xff0c;打通社交渠道&#xff0c;经营私域会员&#xff0c;带来传统电商和线下门店之外的生意增量。

揭秘Etched AI:三个哈佛辍学00后挑战英伟达,推出Transformer专用ASIC芯片sohu

人工智能领域最近掀起了一股新的热潮&#xff0c;三位哈佛辍学的00后本科生创建了Etched AI&#xff0c;并成功推出了一款超强AI芯片sohu&#xff0c;直指英伟达的AI芯片帝国。这款芯片被誉为比英伟达H100快20倍&#xff0c;吸引了众多科技界的关注。本文将深入探讨Etched AI及…

“实时数据大屏2k、4k、8k”这样做【高级前端必备技能之一】

&#x1f525;废话不多先上效果图 &#x1f525;划重点 新手程序员需要注意以下几点&#xff1a; 我们需要进行充分的技术调研&#xff0c;进行技术选型产品&#xff0c;UI&#xff0c;再三确认效果图是否确定&#xff0c;避免后续出现返工的情况 不能拿到效果图之后&#x…

【分布式计算框架 MapReduce】MapReduce 初级编程

目录 一、MapReduce 示例程序的导入并运行测试 二、准备 4 个小文件&#xff08;文件大小分别为 1.7M&#xff0c;5.1M&#xff0c;3.4M&#xff0c;6.8M&#xff09; 1. 第一种情况&#xff0c;默认分片&#xff1a;不修改程序代码&#xff0c;直接使用 WordCount 源程序 2…

电脑提示vcomp140.dll丢失的几种有效的解决方法,轻松搞定dll问题

在电脑使用过程中&#xff0c;我们可能会遇到一些错误提示&#xff0c;其中之一就是找不到vcomp140.dll。那么&#xff0c;究竟什么是vcomp140.dll呢&#xff1f;为什么会出现找不到vcomp140.dll的情况呢&#xff1f;本文将从vcomp140.dll的定义、常见原因、对电脑的影响以及解…

如何理解CI/CD的概念及其在Java项目中的应用

CI/CD 是持续集成&#xff08;Continuous Integration&#xff09;和持续交付/部署&#xff08;Continuous Delivery/Deployment&#xff09;的缩写。它是一种现代软件开发实践&#xff0c;用于提高代码发布的频率和质量&#xff0c;确保软件系统的稳定性和一致性。通过自动化构…

19.《C语言》——【如何理解static和extern?】

&#x1f387;开场语 亲爱的读者&#xff0c;大家好&#xff01;我是一名正在学习编程的高校生。在这个博客里&#xff0c;我将和大家一起探讨编程技巧、分享实用工具&#xff0c;并交流学习心得。希望通过我的博客&#xff0c;你能学到有用的知识&#xff0c;提高自己的技能&a…

解锁iCloud的全能潜力:从新手到专家的终极指南!

在今天这个数字化日益发达的时代&#xff0c;云服务已经成为我们生活中不可或缺的一部分。苹果公司的iCloud服务&#xff0c;作为一个集成的云服务平台&#xff0c;为用户提供了数据存储、备份、同步等多样化的功能。通过本文&#xff0c;我们将深入探讨如何高效利用iCloud&…

[单机版架设]新天堂2-死亡骑士338|带AI机器人

前言 今天给大家带来一款单机游戏的架设&#xff1a;新天堂2-死亡骑士338单机服务端—带AI机器人 如今市面上的资源参差不齐&#xff0c;大部分的都不能运行&#xff0c;本人亲自测试&#xff0c;运行视频如下&#xff1a; 新天堂2 搭建教程 此游戏架设不需要虚拟机&#xf…

识图生成代码:通义千问vsGPt4o,有点小崩

今日对比一下通义千问和GPt4o&#xff0c;在通过识别图片然后去生成前端代码 在当今ai的时代&#xff0c;通过ai去生成页面的代码可以很大的提高我们的开发效率下面是我们要求的生成的图片截图&#xff0c;这是掘金的榜单 效果对比 首先我们使用通义千问&#xff0c;让他去帮我…

C++11中引入的auto关键字和范围for循环(range-based for loop)。

C11中引入的auto关键字和范围for循环&#xff08;range-based for loop&#xff09;是两项重要的新特性&#xff0c;它们旨在提高代码的可读性和简洁性&#xff0c;同时减少编写错误。 auto关键字 auto关键字在C11中被赋予了新的含义&#xff0c;用于自动类型推断。在C11之前…

Django 自定义过滤器

1&#xff0c;编写自定义过滤器并注册 创建目录 Test/app5/templatetags 分别创建文件 Test/app5/templatetags/__init__.py Test/app5/templatetags/myfilter.py 添加过滤器脚本 Test/app5/templatetags/myfilter.py from django import template register template.…

Python功能制作之使用streamlit做一个简单的WebUI

使用Streamlit创建WebUI 1. 什么是Streamlit Streamlit 是一个开源的Python库&#xff0c;用于快速创建美观的Web应用。 它适合数据科学家和机器学习工程师&#xff0c;因为它能够以最小的代码量将数据应用程序带到浏览器中。通过简单的Python脚本&#xff0c;可以创建交互式…

c++类和对象(三)日期类

类和对象 一.拷贝构造函数定义二.拷贝构造函数特征三.const成员函数权限权限的缩小权限的缩放大 四.隐式类型转换 一.拷贝构造函数定义 拷贝构造函数&#xff1a;只有单个形参&#xff0c;该形参是对本类类型对象的引用(一般常用const修饰)&#xff0c;在用已存 在的类类型对象…

kettle创建资源库无法登录问题

问题&#xff1a;You dont seem to be getting a connection to the server. Please check the path youre using and make sure the server is up and running. 1. 删除资源库 2.删除数据库中R_开头的表 3.重新创建资源库连接&#xff0c;查看是否成功产生表 4.创建成功&…

如何在离线环境下安装Docker社区版

目录 1. 引言 2. 准备工作 3. 下载Docker安装包 4. 下载Docker的依赖包 5. 将安装包传输到目标系统 6. 安装Docker社区版 7. 配置Docker 8. 解决常见问题 9. 维护和更新Docker 10. 创建离线安装脚本 11. 使用离线镜像 12. 高级配置与优化 13. 安全性考虑 14. 总结…

005-GeoGebra基础篇-GeoGebra的矩形

上一篇关于点的介绍已经触及到了诸多GeoGebra的基础操作&#xff0c;这一篇我们根据画矩形&#xff0c;继续探索GeoGebra。 目录 一、最粗暴的方式绘制矩形1. 使用“Polygon”工具直接绘制2. 注意看代数列表3. 关于矩形和线段 二、用点和线段绘制矩形&#xff08;1&#xff09;…

52、基于K 均值聚类实现基于颜色的分割(matlab)

1、K 均值聚类实现基于颜色的分割原理及流程 K 均值聚类是一种常用的聚类算法&#xff0c;通过将数据点分配到 K 个簇中&#xff0c;每个簇的中心代表簇的平均值来实现聚类的目的。 基于颜色的分割的原理是利用像素的颜色信息来对图像进行分割。首先需要将图像的每个像素点表…

计算机网络微课堂(湖科大教书匠)TCP部分

计算机网络微课堂&#xff08;湖科大教书匠&#xff09;TCP部分 【计算机网络微课堂&#xff08;有字幕无背景音乐版&#xff09;】 TCP的流量控制 一般来说&#xff0c;我们希望数据传输得更快一些。但如果发送方把数据发送得过快&#xff0c;接收方就可能来不及接收&#…