当前位置: 首页 > article >正文

Harmonyos多线程之Worker基本使用

Harmonyos多线程之Worker基本使用

  • Worker的注意事项
    • 创建Worker的注意事项
      • 手动创建Worker线程
      • 自动创建Worker现成
    • 跨har包加载Worker
    • 多级Worker的声明周期管理
  • Worker和宿主线程的通信

Worker主要作用是为应用程序提供一个多线程的运行环境,可满足应用程序在执行过程中与宿主线程分离,在后台线程中运行一个脚本进行耗时操作,极大避免类似于计算密集型或高延迟的任务阻塞宿主线程的运行。具体接口信息及使用方法详情请见Worker

Worker的注意事项

  • Worker创建后需要手动管理生命周期,且最多同时运行的Worker子线程数量为64个。
    • Worker的创建和销毁耗费性能,建议开发者合理管理已创建的Worker并重复使用。Worker空闲时也会一直运行,因此当不需要Worker时,可以调用terminate()接口或close()方法主动销毁Worker。若Worker处于已销毁或正在销毁等非运行状态时,调用其功能接口,会抛出相应的错误。
    • Worker的数量由内存管理策略决定,设定的内存阈值为1.5GB和设备物理内存的60%中的较小者。在内存允许的情况下,系统最多可以同时运行64个Worker。如果尝试创建的Worker数量超出这一上限,系统将抛出错误:“Worker initialization failure, the number of workers exceeds the maximum.”。实际运行的Worker数量会根据当前内存使用情况动态调整。一旦所有Worker和主线程的累积内存占用超过了设定的阈值,系统将触发内存溢出(OOM)错误,导致应用程序崩溃。
  • 由于不同线程中上下文对象是不同的,因此Worker线程只能使用线程安全的库,例如UI相关的非线程安全库不能使用。
  • 序列化传输的数据量大小限制为16MB
  • 使用Worker模块时,需要在宿主线程中注册onerror接口,否则当Worker线程出现异常时会发生jscrash问题。
  • 不支持跨HAP使用Worker线程文件
  • 不支持在Worker工作线程中使用AppStorage

创建Worker的注意事项

Worker线程文件需要放在"{moduleName}/src/main/ets/"目录层级之下,否则不会被打包到应用中。有手动和自动两种创建Worker线程目录及文件的方式。

手动创建Worker线程

开发者需要手动创建相关目录及文件, 此时需要配置build-profile.json5的相关字段信息,Worker线程文件才能确保被打包到应用中

在当前使用Worker线程的模块下面的对应文件目录中创建一个worker线程文件, 并增加相关配置项
在这里插入图片描述

手动创建Worker需要实现代码:

import worker, { ErrorEvent, MessageEvents, ThreadWorkerGlobalScope } from '@ohos.worker'
import { JSON } from '@kit.ArkTS'

// 创建woker线程中和宿主线程通信的对象
const workerPort: ThreadWorkerGlobalScope = worker.workerPort

//woker线程接受主线程的消息
workerPort.onmessage = (e: MessageEvents) => {
  // 现成通信的具体逻辑
  console.log("onmessage=22222================" + JSON.stringify(e.data))

  // woker线程像宿主线程发送消息
  workerPort.postMessage("woker线程发送消息")
}

// 回调函数。表示当Worker对象接收到一条无法被序列化的消息时被调用的事件处理程序,
// 处理程序在宿主线程中执行。其中回调函数中event类型为MessageEvents,表示收到的Worker消息数据。
workerPort.onmessageerror = (ev: MessageEvents) => {
  console.log('onmessageerror=================' + JSON.stringify(ev.data))
}

// worker线程发生error错误的回调
workerPort.onerror = (err: ErrorEvent) => {
  console.log("worker.ets onerror" + err.message);
}

自动创建Worker现成

DevEco Studio支持一键生成Worker,在对应的{moduleName}目录下任意位置,点击鼠标右键 > New > Worker,即可自动生成Worker的模板文件及配置信息,无需再手动在build-profile.json5中进行相关配置。
在这里插入图片描述
当我们使用工具进行自动创建时, 我们可以看到配置文件中自动增加了,工具创建的AutoWorker线程类:
在这里插入图片描述

使用自动创建的方式,系统自动实现的代码:

import { ErrorEvent, MessageEvents, ThreadWorkerGlobalScope, worker } from '@kit.ArkTS';

const workerPort: ThreadWorkerGlobalScope = worker.workerPort;

/**
 * Defines the event handler to be called when the worker thread receives a message sent by the host thread.
 * The event handler is executed in the worker thread.
 *
 * @param e message data
 */
workerPort.onmessage = (e: MessageEvents) => {
}

/**
 * Defines the event handler to be called when the worker receives a message that cannot be deserialized.
 * The event handler is executed in the worker thread.
 *
 * @param e message data
 */
workerPort.onmessageerror = (e: MessageEvents) => {
}

/**
 * Defines the event handler to be called when an exception occurs during worker execution.
 * The event handler is executed in the worker thread.
 *
 * @param e error message
 */
workerPort.onerror = (e: ErrorEvent) => {
}

跨har包加载Worker

跨har的worker线程:
在这里插入图片描述

在entry模块中使用workerhar模块中创建的worker线程:

//宿主线程中创建woker线程
          const workerInstance = new worker.ThreadWorker("@workerhar/ets/workers/Worker.ets")

          //宿主线程像woker线程发送消息
          workerInstance.postMessage("宿主线程像夸har包的woker线程传递消息========")

          //宿主线程接受woker线程信息
          workerInstance.onmessage = (e: MessageEvents) => {
            console.log('onmessage=接受到夸har包的worker线程消息====================' + JSON.stringify(e.data))


            //销毁Worker对象
            workerInstance.terminate()
          }

          // 在调用terminate后,执行onexit
          workerInstance.onexit = (code) => {
            console.log("main thread terminate");
          }

          workerInstance.onerror = (err: ErrorEvent) => {
            console.log("main error message " + err.message);
          }

输出结果:
在这里插入图片描述

注意: 主要区别是在与worker文件的导入路径

多级Worker的声明周期管理

由于支持创建多级Worker(即通过父Worker创建子Worker的机制形成层级线程关系),且Worker线程生命周期由用户自行管理,因此需要注意多级Worker生命周期的正确管理。若用户销毁父Worker时未能结束其子Worker的运行,会产生不可预期的结果。建议用户确保子Worker的生命周期始终在父Worker生命周期范围内,并在销毁父Worker前先销毁所有子Worker。

示例:

主线程核心代码:

// 在主线程创建worker线程(父worker),在worker线程中在次创建worker线程(子线程)
        const parentworker = new worker.ThreadWorker('../workers//ParentWorker')

        parentworker.onmessage = (e: MessageEvents) => {
          console.log('主线程收到父worker线程信息========================' + e.data)
        }

        parentworker.onexit = () => {
          console.log("父worker退出=============================")
        }

        parentworker.onerror = (error: ErrorEvent) => {
          console.log('主线程收到父worker的报错=======================' + error)
        }

        parentworker.postMessage('主线程发送消息给父worker')
      })

parentworker.ets的核心代码

workerPort.onmessage = (e: MessageEvents) => {
  if (e.data === "主线程发送消息给父worker") {
    // 创建一个子worker
    let childworker = new worker.ThreadWorker("../workers/ChilderWorker");

    childworker.onmessage = (e: MessageEvents) => {
      console.log("父Worker收到子Worker的信息================" + e.data);

      if (e.data === '子Worker向父Worker发送信息') {
        workerPort.postMessage("父Worker向主线程发送信息");
      }
    }

    childworker.onexit = () => {
      console.log('子Worker退出=================')
      workerPort.close()
    }

    childworker.onerror = (err: ErrorEvent) => {
      console.log("子Worker发生报错 " + err);
    }

    childworker.postMessage("父Worker向子Worker发送信息");
  }
}

childerworker.ets核心代码:

workerPort.onmessage = (e: MessageEvents) => {
  if (e.data === "主线程发送消息给父worker") {
    // 创建一个子worker
    let childworker = new worker.ThreadWorker("../workers/ChilderWorker");

    childworker.onmessage = (e: MessageEvents) => {
      console.log("父Worker收到子Worker的信息================" + e.data);

      if (e.data === '子Worker向父Worker发送信息') {
        workerPort.postMessage("父Worker向主线程发送信息");
      }
    }

    childworker.onexit = () => {
      console.log('子Worker退出=================')
      workerPort.close()
    }

    childworker.onerror = (err: ErrorEvent) => {
      console.log("子Worker发生报错 " + err);
    }

    childworker.postMessage("父Worker向子Worker发送信息");
  }
}

Worker和宿主线程的通信

worker的代码是上面的手动创建worker示例的代码.

示例代码:

//宿主线程中创建woker线程
          const workerInstance = new worker.ThreadWorker("../manualcreate/manualWorker")

          //宿主线程像woker线程发送消息
          workerInstance.postMessage("宿主线程像woker线程传递消息========")

          //宿主线程接受woker线程信息
          workerInstance.onmessage = (e: MessageEvents) => {
            console.log('onmessage=1111====================' + JSON.stringify(e.data))


            //销毁Worker对象
            workerInstance.terminate()
          }

          // 在调用terminate后,执行onexit
          workerInstance.onexit = (code) => {
            console.log("main thread terminate");
          }

          workerInstance.onerror = (err: ErrorEvent) => {
            console.log("main error message " + err.message);
          }

输出结果:
在这里插入图片描述


http://www.kler.cn/a/444885.html

相关文章:

  • 前端跨越方式有哪些
  • Jenkins 中 写 shell 命令执行失败,检测失败问题
  • Linux常用命令【真·常用】
  • DGCN论文解读
  • Python读取Excel批量写入到PPT生成词卡
  • 配置免密登陆服务器
  • python快速接入阿里云百炼大模型
  • 【数据分析】数据分析流程优化:从数据采集到可视化的全面指南
  • 一篇文章理解前端的请求头和响应头含义
  • 打 印 菱 形
  • Gartner发布2025年网络安全主要趋势:实现转型和嵌入弹性两大主题下的9个趋势
  • Linux性能监控命令_nmon 安装与使用以及生成分析Excel图表
  • 基于注意力机制的ResNet优化算法(三种注意力机制+源码+pytorch)
  • 4、交换机IP接口功能
  • git 删除鉴权缓存及账号信息
  • 基于时间情境创造与 AI 智能名片 S2B2C 商城小程序源码的零售创新策略研究
  • 从零开始学习HTML5
  • 【Linux】文件IO--read/write/缓冲区(详)
  • 防火墙规则配置错误导致的网络问题排查
  • 用C#(.NET8)开发一个NTP(SNTP)服务