鸿蒙中 线程间通信
本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
一、线程的实现方式
鸿蒙提供了多种线程管理方案,适用于不同场景:
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.tsimport 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. 发送消息到Workerworker.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
。 - 通过
postMessage
和onmessage
实现双向通信。
二、线程间通信(IPC)方式
1. 消息传递(Worker/TaskPool)
- 机制:基于序列化数据的跨线程消息。
- 适用场景:ArkTS/JS层线程通信。
postMessage
worker.postMessage({key: value})
onmessage
worker.onmessage = (msg) => {}
terminate
worker.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}`);});
三、线程与通信的选择策略
四、注意事项
1. 常见问题
-
问题1:Worker文件路径错误 解决:确保路径为
entry/ets/workers/文件名.ts
。 -
问题2:TaskPool任务参数不可序列化 解决:仅传递基本类型、数组、普通对象。
2. 性能优化
- 减少通信次数:合并多次
postMessage
为批量操作。 - 共享内存:大数据传输优先用
SharedArrayBuffer
。