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

news2024/7/2 3:36:46

上篇回顾: 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.message
      promptAction.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.message
    promptAction.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.coloradmin.cn/o/1877623.html

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

相关文章

kicad第三方插件安装问题

在使用KICAD时想安装扩展内容&#xff0c;但是遇到下载失败&#xff0c;因为SSL connect error。 因为是公司网络&#xff0c;我也不是很懂&#xff0c;只能另寻他法。找到如下方法可以曲线救国。 第三方插件包目录 打开存放第三方插件存放目录&#xff0c;用于存放下载插件包…

什么是中断?---STM32篇

目录 一&#xff0c;中断的概念 二&#xff0c;中断的意义 三&#xff0c;中断的优先级 四&#xff0c;中断的嵌套 如果一个高优先级的中断发生&#xff0c;它会立即打断当前正在处理的中断&#xff08;如果其优先级较低&#xff09;&#xff0c;并首先处理这个高优…

AGPT•intelligence:带你领略全新量化交易的风采

随着金融科技的快速发展&#xff0c;量化交易已经成为了投资领域的热门话题。越来越多的投资者开始关注和使用量化交易软件来进行投资决策。在市场上有许多量化交易软件可供选择。 Delaek&#xff0c;是一位资深的金融科技专家&#xff0c;在 2020年成立一家专注于数字资产量化…

【全球首个开源AI数字人】DUIX数字人-打造你的AI伴侣!

目录 1. 引言1.1 数字人技术的发展背景1.2 DUIX数字人项目的开源意义1.3 DUIX数字人技术的独特价值1.4 本文目的与结构 2. DUIX数字人概述2.1 定义与核心概念2.2 硅基智能与DUIX的关系2.3 技术架构2.4 开源优势2.5 应用场景2.6 安全与合规性 3. DUIX数字人技术特点3.1 开源性与…

[OtterCTF 2018]Bit 4 Bit

我们已经发现这个恶意软件是一个勒索软件。查找攻击者的比特币地址。** 勒索软件总喜欢把勒索标志丢在显眼的地方&#xff0c;所以搜索桌面的记录 volatility.exe -f .\OtterCTF.vmem --profileWin7SP1x64 filescan | Select-String “Desktop” 0x000000007d660500 2 0 -W-r-…

Java新手启航:Windows下JDK安装,开启编程之旅

你是不是对编程充满好奇&#xff0c;想要迈入Java的世界&#xff0c;却不知道从何开始&#xff1f;别担心&#xff0c;每一个Java大师都是从安装JDK开始的&#xff0c;而今天&#xff0c;我将手把手教你如何轻松完成JDK的安装&#xff0c;让你迈出编程之旅的第一步! 接下来&am…

[Cloud Networking] BGP

1. AS (Autonomous System) 由于互联网规模庞大&#xff0c;所以网络会被分为许多 自治系统&#xff08;AS-Autonomous system&#xff09;。 所属类型ASN名称IPv4 数量IPv6数量运营商ISPAS3356LEVEL3 - Level 3 Parent, LLC, US29,798,83273,301,954,048互联网企业AS15169GO…

vue组件全局注册

描述&#xff1a; vue组件的注册分为局部和全局注册两部分&#xff0c;局部注册相对容易&#xff0c;不做赘述&#xff1b;而不同框架的注册方法又有所不同&#xff0c;下面针对vite框架和vue-cli框架的注册分别进行说明 vue组件全局注册 一、vite框架中全局组件注册二、Vue-cl…

AI复活亲人市场分析:技术、成本与伦理挑战

“起死回生”这种事&#xff0c;过去只存在于科幻电影里&#xff0c;但今年&#xff0c;被“复活”的案例却越来越多。 2月底&#xff0c;知名音乐人包晓柏利用AI“复活”了她的女儿&#xff0c;让她在妈妈生日时唱了一首生日歌&#xff1b;3月初&#xff0c;商汤科技的年会上…

ComfyUI汉化插件安装

步骤一&#xff1a;点击Manager 步骤二&#xff1a;选择安装插件 步骤三&#xff1a;搜索Translation&#xff0c;选择第一个点击右边得安装 步骤四&#xff1a;点击下放得RESTART进行重启 步骤五&#xff1a;等待重启完成后&#xff0c;点击设置 步骤六&#xff1a;选择中文语…

day02-Spark集群及参数

一、Spark运行环境变量问题(了解) 1-pycharm远程开发运行时&#xff0c;执行的是服务器的代码 2-通过本地传递指令到远程服务器运行代码时&#xff0c;会加载对应环境变量数据&#xff0c;加载环境变量文件是用户目录下的.bashrc文件 在/etc/bashrc 1-1 在代码中添加 使用os模块…

[方法] Unity 3D模型与骨骼动画

1. 在软件中导出3D模型 1.1 3dsmax 2014 1.1.1 TGA转PNG 3dsmax的贴图格式为tga&#xff0c;我们需要在在线格式转换中将其转换为Unity可识别的png格式。 1.1.2 模型导出 导出文件格式为fbx。在导出设置中&#xff0c;要勾选三角算法&#xff0c;取消勾选摄像机和灯光&#…

海康车牌识别 报警回调后程序崩溃

我用的32位 6.1.9版本SDK 回调会导致程序崩溃 咨询了下海康官方技术 答复如下&#xff1a;&#xff08;此答复我没尝试 自行尝试 我的解决方法是更换了老版本 5.3版本 没什么问题 个人资源中有 自行下载

grpc学习golang版( 四、多服务示例 )

系列文章目录 第一章 grpc基本概念与安装 第二章 grpc入门示例 第三章 proto文件数据类型 第四章 多服务示例 第五章 多proto文件示例 第六章 服务器流式传输 第七章 客户端流式传输 第八章 双向流示例 文章目录 一、前言二、定义proto文件三、编写server服务端四、编写Client客…

【漏洞复现】安美数字酒店宽带运营系统——命令执行漏洞(CNVD-2021-37784)

声明&#xff1a;本文档或演示材料仅供教育和教学目的使用&#xff0c;任何个人或组织使用本文档中的信息进行非法活动&#xff0c;均与本文档的作者无关。 文章目录 漏洞描述漏洞复现测试工具 漏洞描述 安美数字酒店宽带运营系统 server_ping.php 存在远程命令执行漏洞&#…

3.3V到5V的负电源产生电路(电荷泵电压反相器)SGM3204输出电流0.2A封装SOT23-6

前言 SGM3204 非稳压 200mA 电荷泵负电源产生电路&#xff0c;LCEDA原理图请访问资源 SGM3204电荷泵负电源产生电路 SGM3204电荷泵负电源产生电路 一般描述 SGM3204从 1.4V 至 5.5V 的输入电压范围产生非稳压负输出电压。 该器件通常由 5V 或 3.3V 的预稳压电源轨供电。由于…

OpenGL3.3_C++_Windows(19)

Demo演示 1 几何着色器 几何Geometry glsl 发生在什么阶段&#xff1f; 图形渲染管线&#xff1a; 顶点数据——顶点着色器阶段——图元装配;&#xff08;Geometry glsl &#xff09;——光栅化阶段——裁切——片段着色器——测试和混合可选的Geometry几何着色器&#xff08;…

龙芯久久派到手开机测试

今天刚拿到龙芯久久派&#xff0c;没看到文档&#xff0c;只有视频&#xff0c;我来写个博客&#xff0c;做个记录&#xff0c;免得以后忘记 1.连接usb转ttl串口与龙芯久久派&#xff0c;如图所示。 2.将usb转串口接到电脑USB口 也就是这个接电脑上 3.打开串口调试助手或Secu…

前端路由管理

前端路由管理简介&#xff1a; 当谈到前端路由管理时&#xff0c;通常指的是在单页面应用程序&#xff08;SPA&#xff09;中管理页面间导航和URL的过程。路由管理器是一个工具&#xff0c;可以帮助前端开发者定义应用程序的不同视图之间的关系&#xff0c;同时能够响应URL的改…

广东省钟表行业协会第十二届会员大会暨2024年钟表行业发展交流会

6月25日广东省钟表行业协会第十二届会员大会暨2024年钟表行业发展交流会在广州万富希尔顿酒店隆重召开。大会选举沙胜昔为广东省钟表行业协会第十二届理事会会长。 领导发言 新任会长 沙胜昔 首席荣誉会长 吴伟阳 新老会长交接仪式 本次大会&#xff0c;全国钟表大伽齐参与…