HarmonyOS应用开发-关于鸿蒙中的异步(Promise)和线程(taskPool,worker)

45 篇文章 0 订阅
11 篇文章 0 订阅

前言

学习鸿蒙过程中,对于鸿蒙的线程和异步可能会存在很多疑惑,什么是异步,什么时候用异步。或者什么时候用线程?

本文重点讲下三种方法的区别和使用场景,不注重具体如何使用代码,这里一笔带过。

鸿蒙对于异步提供了三种处理方式(注意这里是异步,不是特指线程):

1.JS原生的Promise异步
2.taskPool线程
3.worker常驻线程

Promise异步

对于我们做 Android开发,经常提到异步,就习惯性的认为是起个子线程来执行。但是当我们做鸿蒙开发时候,要注意Promise异步和线程两个概念不同。

1.Promise异步仍然是在当前线程中运行任务,结果以异步方式返回(接口回调方式)
2.当我们对某个方法定义为Promise异步执行,那么当前线程就会在空闲时候执行当前方法,结果以异步方式返回

使用方法

●方法1

 testFunc(suc: boolean): Promise<string> {
    return new Promise((resolve, reject) => {
      if (suc) {
        resolve("success")
      } else {
        reject("fail")
      }
    })
  }

●方法2

  async testFunc(suc: boolean): Promise<string> {
    if (suc) {
      return "success"
    }
    throw new Error("fail")
  }

两种方法各有好处,看各自喜欢和习惯以及实际场景。

调用

●场景1 - 异步执行方法获取结果

testFunc1(true).then((result: string) => {
      // resolve返回的结果在这里输出
    }).catch((e: Error) => {
      // reject 抛出的异常在这里触发
    })

●场景2 - 同步等待方法执行完成

async call() {
    try {
      const suc = await this.testFunc(true)
    } catch (e) {
      // reject error
    }
  }

场景2使用了await修饰,改修饰符要求方法必须使用async修饰,且异常通过try…catch来捕获。

Promise使用场景

1.模块或者接口通过异步封装
2.单次IO操作(网络或小文件读写)
3.耗时操作(非长时间耗时,必须保证CPU可以被释放)

taskPool

对于一些耗时操作,使用Promise占用了主线程资源,可能会导致ANR,所以出现了taskPool来保证可以起子线程处理耗时操作。

taskPool存活最长时间为3分钟,运行超过3分钟,那么会被系统杀掉。
  
如果在taskPool里进行了网络请求或者文件读写,那么网络请求和文件读写的耗时是不计算在3分钟里的。

由于鸿蒙线程使用了Actor模型,导致taskPool新起的子线程和主线程的内存是不共享的。所以无法在子线程直接操作主线程的内存。

一定程度上解决了多线程问题,但是对于多线程操作也带来一定的影响。

注意这里是一定程度上解决多线程问题,实质上多线程问题还是会存在。比如主线程和子线程同时对一个文件进行读写操作,会存在多线程问题。

由于内存隔离机制,所以子线程在启动时候,可以接收来自主线程的数据只能是二进制流或者基本数据类型。同理 子线程运行完毕后,可以回传数据给主线程,也只能是二进制流或者基本数据类型。推荐使用JSON字符串。

使用方法

class TestA {
  execute() {
    taskpool.execute(calc, "123sss").then((result) => {
      const target = result as number
    })
  }
}

@Concurrent
function calc(value: string): number {
  return 123
}

注意对于taskPool调用的函数,必须声明为全局函数,且使用 装饰器 @Concurrent 来修饰。
    
    如果条件不满足,那么运行时候,系统会打印错误日志进行提示。

E     [ecmascript] Function is not concurrent
E     [(worker.cpp:414)(InitTaskPoolFunc)] taskpool:: InitTaskPoolFunc fail

Worker

我们经常会遇到,存在一个特别耗时的操作,或者可能存在业务需要一直死循环运行。那么这个时候就涉及到常驻线程了。
  
通过worker可以启动一个线程,该线程不存在时长限制,可以一直存在,所以我们可以在里边做一些耗时操作。

但是有几个特点:

1.worker线程最多可以在APP里同时存在8个一起运行,超出数量的不会运行。但是创建可以创建多个,所以当worker不需要的时候要及时停止运行
2.worker对内存有影响,每个空worker起来后就会占用2MB左右内存
3.worker里可以继续启动taskPool执行逻辑

如何使用

worker 比较特殊,需要在当前module的build-profile.json5配置文件中配置一下worker定义的文件的路径。
在这里插入图片描述

该wSocketWorker文件中,会通过系统 workerPort.onmessage 来接收来自主线程或其他线程的信息,接收到信息后进行处理。
在这里插入图片描述

workerPort通过如下方式声明。

let workerPort: ThreadWorkerGlobalScope = worker.workerPort;

该SocketWorker是我们自定义的一个文件,可以看做是我们当前定义的Worker和其他线程交互的一个接口,也是当前Worker线程的入口。
    注意这里使用workerPort要在全局环境中使用,不能放到类中。

如何在主线程和Worker交互

  test() {
    let send = new worker.ThreadWorker("./SocketWorker.ets");
    send.onexit = (code) => {
      // 运行结束时候,接收来自worker的信息
    }
    send.postMessage(new SocketParam(1, 2, "s", 2, 3))
  }

我们在主线程需要启动worker和worker交互的地方,通过上述代码即可启动我们定义好的worker。同时在onexit监听worker结束时候的回调。

对比Promise,taskPool和worker

1.对于单次IO,非阻塞性任务,可以使用Promise
2.对于UI刷新频繁的场景,不推荐使用Promise执行一些耗时逻辑,可能会造成UI刷新卡顿或者Promise逻辑无法得到执行
3.对于IO密集型任务,非常驻任务,建议使用taskPool执行。控制好时间,不要超过3分钟
4.对于常驻任务,使用worker
5.对于耗时,阻塞任务使用worker
6.使用Promise时候不需要考虑多线程问题,使用worker和taskPool时候,如果对文件进行写操作,注意多线程问题。

写在最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。

这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。

希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

鸿蒙(HarmonyOS NEXT)最新学习路线

在这里插入图片描述

有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。

获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

《鸿蒙 (OpenHarmony)开发入门教学视频》

在这里插入图片描述

《鸿蒙生态应用开发V2.0白皮书》

在这里插入图片描述

《鸿蒙 (OpenHarmony)开发基础到实战手册》

OpenHarmony北向、南向开发环境搭建

在这里插入图片描述

《鸿蒙开发基础》

●ArkTS语言
●安装DevEco Studio
●运用你的第一个ArkTS应用
●ArkUI声明式UI开发
.……
在这里插入图片描述

《鸿蒙开发进阶》

●Stage模型入门
●网络管理
●数据管理
●电话服务
●分布式应用开发
●通知与窗口管理
●多媒体技术
●安全技能
●任务管理
●WebGL
●国际化开发
●应用测试
●DFX面向未来设计
●鸿蒙系统移植和裁剪定制
……
在这里插入图片描述

《鸿蒙进阶实战》

●ArkTS实践
●UIAbility应用
●网络案例
……
在这里插入图片描述

获取以上完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料

  • 15
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在传统的Node.js,JavaScript是单线程的,这意味着在Node.js的主线程只能执行一个任务,这可能导致性能瓶颈。为了解决这个问题,Node.js引入了跑多线程的概念。 然而,在Node.js,直接使用多线程需要使用C/C++编写核心模块,这对大多数JavaScript开发者来说可能是一个挑战。为了简化多线程编程,Node.js提供了一个称为Worker Threads(工作线程)的模块,可以方便地在Node.js应用创建和管理多线程。 虽然Worker Threads提供了多线程的支持,但在某些情况下,仍然可能会遇到报错。这些报错可能是由于以下原因之一: 1. 内存限制:每个线程都有自己的内存空间,如果线程使用的内存超过了系统限制,会导致报错。 2. 线程间通信问题:多线程之间需要进行通信,如果通信出现问题或不当使用线程间的共享资源,可能导致报错。 3. 异步操作:多线程异步操作可能会引起线程安全问题,需要注意正确地处理异步操作。 解决这些报错可以采取以下措施: 1. 检查内存使用情况,如果超过系统限制,考虑优化代码或增加系统内存。 2. 确保正确地使用线程间的共享资源,并避免出现竞争条件。 3. 使用合适的同步或异步机制来处理多线程异步操作,例如使用Promise异步队列来确保线程安全。 总之,虽然在Node.js跑多线程可以提高性能,但需要注意处理一些潜在的问题,避免出现报错。合理使用Worker Threads模块并采取适当的措施可以确保多线程在Node.js应用的成功运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值