鸿蒙中 线程间通信

本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

一、线程的实现方式

鸿蒙提供了多种线程管理方案,适用于不同场景:

1. 基于ArkTS/JS的异步任务(TaskPool)
  • 用途:执行CPU密集型任务(如数据处理、图像解码)。
  • 特点
    • 轻量级线程池(TaskPool)管理,自动调度。
    • 任务之间隔离,崩溃不影响主线程。
  • 示例
  import taskpool from '@ohos.taskpool';

  @Concurrent
  function computeTask(data: number): number {
    return data * 2; // 在子线程中执行
  }

  async function runTask() {
    const task = new taskpool.Task(computeTask, 100);
    const result = await taskpool.execute(task); // 提交到线程池
    console.log(`Result: ${result}`);
  }

关键点

  • @Concurrent 装饰器是必须的,表示该函数可并发执行。
  • 任务参数需可序列化(不支持回调函数、类实例等)。
2. Worker线程
  • 用途:长时间运行的后台任务(如网络请求、文件IO)。
  • 特点
    • 独立线程,与主线程通过消息通信。
    • 需单独创建worker.ts文件。
  • 示例

步骤1:创建Worker文件entry/src/main/ets/workers目录下创建FileWorker.ts

// workers/FileWorker.ts
import worker from '@ohos.worker';

// 1. 获取Worker通信端口
const workerPort = worker.workerPort;

// 2. 监听主线程消息
workerPort.onmessage = (msg: MessageEvents) => {
  console.log(`Worker收到消息: ${JSON.stringify(msg.data)}`);
  // 模拟耗时操作(如文件处理)
  setTimeout(() => {
    workerPort.postMessage({ status: 'done', result: msg.data * 2 }); // 返回结果
  }, 1000);
};

// 3. 错误处理
workerPort.onerror = (err: ErrorEvent) => {
  console.error(`Worker发生错误: ${err.message}`);
};

步骤2:主线程调用

// 主线程代码
const worker = new worker.ThreadWorker('entry/ets/workers/FileWorker.ts');

// 1. 发送消息到Worker
worker.postMessage(42); // 传递数据

// 2. 接收Worker返回结果
worker.onmessage = (msg: MessageEvents) => {
  console.log(`主线程收到结果: ${JSON.stringify(msg.data)}`); 
  // 输出: 主线程收到结果: {"status":"done","result":84}
};

// 3. 销毁Worker(不再需要时)
worker.terminate();

关键点

  • Worker文件路径需相对于entry/src/main/ets
  • 通过postMessageonmessage实现双向通信。

二、线程间通信(IPC)方式

1. 消息传递(Worker/TaskPool)
  • 机制:基于序列化数据的跨线程消息。
  • 适用场景:ArkTS/JS层线程通信。
方法说明示例
postMessage发送消息worker.postMessage({key: value})
onmessage接收消息worker.onmessage = (msg) => {}
terminate终止Workerworker.terminate()
2. 共享内存(SharedArrayBuffer)
  • 机制:多线程直接读写同一块内存。
  • 注意:需手动同步避免竞态条件。
// 主线程
const sharedBuffer = new SharedArrayBuffer(16);
const intArray = new Int32Array(sharedBuffer);

// 线程A写入
Atomics.store(intArray, 0, 123);

// 线程B读取
const value = Atomics.load(intArray, 0);
console.log(value); // 输出: 123

注意:必须使用Atomics API避免竞态条件。 

3. 事件通知(Emitter)
  • 机制:通过事件总线跨线程触发回调。
import emitter from '@ohos.events.emitter';

// 线程A发布事件
emitter.emit({
  eventId: 1, // 事件ID
  priority: emitter.EventPriority.HIGH // 优先级
}, {
  data: { key: 'value' } // 事件数据
});

// 线程B订阅事件
emitter.on(1, (eventData) => {
  console.log(`收到事件: ${eventData.data.key}`);
});

三、线程与通信的选择策略

场景推荐方案原因
短时CPU密集型任务TaskPool自动管理,避免频繁创建线程
长时后台任务(如下载)Worker隔离性强,崩溃不影响主线程
高性能计算(如音视频)Native线程 + 共享内存减少序列化开销,提升速度
跨进程通信RPC或分布式能力鸿蒙专为跨设备设计

四、注意事项

1. 常见问题
  • 问题1:Worker文件路径错误 解决:确保路径为entry/ets/workers/文件名.ts

  • 问题2:TaskPool任务参数不可序列化 解决:仅传递基本类型、数组、普通对象。

2. 性能优化
  • 减少通信次数:合并多次postMessage为批量操作。
  • 共享内存:大数据传输优先用SharedArrayBuffer

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值