前言
线程是操作系统能够调度的最小计算单位,属于进程的一部分,也是进程中实际运行的实体。在一个应用中,可能存在多个进程,但所有的 UIAbility、ServiceExtensionAbility 和 DataShareExtensionAbility 最终都会在同一个主进程中运行。而同一类型的 ExtensionAbility(除 ServiceExtensionAbility 和 DataShareExtensionAbility 外)都会运行在各自独立的进程中。在鸿蒙开发中,每个进程都拥有一个主线程。
鸿蒙 Stage 模型下的线程类型
在鸿蒙开发的应用进程中,基于 Stage 模型,每个进程都有一个主线程(UI 线程),负责界面更新和用户交互响应等操作。为了避免耗时任务阻塞主线程,从而保证 UI 的流畅性,我们需要创建工作线程来处理这些耗时任务。
主线程的主要职责
1.执行 UI 绘制:主线程处理所有与用户界面相关的操作,包括布局计算、渲染及屏幕刷新。鸿蒙系统中,ArkTs 引擎用于管理主线程上的 UI 渲染。
2.管理 UI 组件:ArkTs 引擎实例管理多个 UIAbility 组件,使它们能够在主线程上运行。
3.管理其他线程:通过 ArkTs 引擎实例管理工作线程,例如通过任务池(TaskPool)创建或取消任务,以及启动和终止工作线程(Worker)。
4.分发交互事件:主线程接收用户的触摸事件及其他系统事件,并分发给相应组件进行处理。
5.消息循环:主线程维护一个消息队列,并通过循环处理这些消息以响应不同应用程序事件。
6.事件和生命周期管理:主线程处理应用代码的各种回调,包括事件处理和生命周期管理。
7.处理工作线程的消息:接收并处理来自任务池和工作线程的消息。
通过这些机制,主线程能够高效地更新 UI 和响应用户交互,同时工作线程处理耗时任务,保证了应用的流畅运行。
线程间通信
为了保证应用的流畅性和响应性,非 UI 相关的耗时操作通常不会在主线程上执行,而是通过创建额外的工作线程或任务来完成。HarmonyOS 提供了两种线程间通信的方式:Emitter 和 Worker。
Emitter(发射器)
Emitter 主要用于线程间的事件同步。它在不同线程之间传递事件并确保事件的顺序和同步性。通过 Emitter,一个线程可以触发事件,而其他线程可以监听并处理这些事件,有助于不同线程之间的数据共享和协调。
import { Emitter, EmitterNamespace } from '@ohos.emitter';
let eventEmitter: EmitterNamespace.Emitter = Emitter.createEventEmitter();
// 订阅事件
function subscribeToEvent() {
eventEmitter.on('myEvent', (data) => {
console.log('Event received: ', data);
// 处理事件逻辑
});
console.log('Subscribed to event.');
}
// 发送事件
function emitEvent() {
const data = { message: 'Hello world!' };
eventEmitter.emit('myEvent', data);
console.log('Event emitted: ', data);
}
// 取消事件
function unsubscribeFromEvent() {
eventEmitter.off('myEvent');
console.log('Unsubscribed from event.');
}
Worker(工作线程)
Worker 主要用于创建一个新线程来执行耗时任务。当需要执行耗时操作时,可以使用 Worker 线程以避免主线程被阻塞。Worker 线程在主线程的上下文中创建并可处理如网络访问、文件读写等任务,从而提高应用的响应性和性能。
通过以上设计,HarmonyOS 能够在保证主线程流畅性的同时,高效处理各种复杂任务,提升应用整体性能和用户体验。
总结
通过 Emitter 和 Worker 方案,HarmonyOS 能够实现多线程间的高效通信和任务处理,从而确保 UI 线程的流畅性和稳定性,同时高效地处理耗时任务。这样不仅提升了应用的整体性能,还优化了用户体验。