鸿蒙开发——线程内通信
1、概 述
在介绍鸿蒙开发中线程间通信问题前,我们先解释下什么是线程。
在计算机科学中,线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。这么说是不是太抽象了?咱们换成通俗的话来说:
假如把一个正在运行的程序想象成一个大工厂。这个工厂在运作的时候,有很多不同的任务要做。线程呢,就像是工厂里的一个的工人小组(不同的科室)。 每个工人小组(线程)都可以独立地干活,去完成特定的一小部分任务。比如有的工人小组专门负责把原材料搬进工厂,有的专门负责在生产线上组装零件,还有的专门负责把成品打包运出去。 这些工人小组可以同时工作,一起努力让工厂的生产效率更高。就像在电脑里,多个线程可以同时进行不同的任务,让程序运行得更快更顺畅。 这些工人小组都是在同一个大工厂(程序)里干活,他们可以共享一些工厂里的资源,比如工具啊、仓库啊之类的。这样就可以更方便地协同工作啦。 |
相应的,我们通过上面的形象的例子了解了什么是线程后,那线程内通信,就可以类比为工人小组之间的消息传递。
2、线程模型
在介绍线程内通信前,我们先了解下鸿蒙应用的线程主要有哪几类,主要分为三类,他们分别的职责说明如下:
1)主线程
-
执行UI绘制。
-
管理主线程的ArkTS引擎实例,使多个UIAbility组件能够运行在其之上。
-
管理其他线程的ArkTS引擎实例,例如使用TaskPool(任务池)创建任务或取消任务、启动和终止Worker线程。
-
分发交互事件。
-
处理应用代码的回调,包括事件处理和生命周期管理。
-
接收TaskPool以及Worker线程发送的消息。
2)TaskPool Worker线程
-
用于执行耗时操作,支持设置调度优先级、负载均衡等功能,推荐使用。
3)Worker线程
-
用于执行耗时操作,支持线程间通信。
TaskPool(任务池)和Worker的作用是为应用程序提供一个多线程的运行环境,用于处理耗时的计算任务或其他密集型任务。可以有效地避免这些任务阻塞主线程,从而最大化系统的利用率,降低整体资源消耗,并提高系统的整体性能。
❓ TaskPool Worker和Worker他们的区别是什么呢?
TaskPool和Worker均支持多线程并发能力。由于TaskPool的工作线程会绑定系统的调度优先级,并且支持负载均衡(自动扩缩容),而Worker需要开发者自行创建,存在创建耗时以及不支持设置调度优先级,故在性能方面使用TaskPool会优于Worker,因此大多数场景推荐使用TaskPool。
TaskPool偏向独立任务维度,该任务在线程中执行,无需关注线程的生命周期,超长任务(大于3分钟且非长时任务)会被系统自动回收;而Worker偏向线程的维度,支持长时间占据线程执行,需要主动管理线程生命周期。
常见的一些开发场景及适用场景说明如下:
-
运行时间超过3分钟(不包含Promise和async/await异步调用的耗时,例如网络下载、文件读写等I/O任务的耗时)的任务【例如后台进行1小时的预测算法训练等CPU密集型任务,需要使用Worker】。
-
有关联的一系列同步任务。例如在一些需要创建、使用句柄的场景中,句柄创建每次都是不同的,该句柄需永久保存,保证使用该句柄进行操作,需要使用Worker。
-
需要设置优先级的任务。例如图库直方图绘制场景,后台计算的直方图数据会用于前台界面的显示,影响用户体验,需要高优先级处理,需要使用TaskPool。
-
需要频繁取消的任务。例如图库大图浏览场景,为提升体验,会同时缓存当前图片左右侧各2张图片,往一侧滑动跳到下一张图片时,要取消另一侧的一个缓存任务,需要使用TaskPool。
-
大量或者调度点较分散的任务。例如大型应用的多个模块包含多个耗时任务,不方便使用Worker去做负载管理,推荐采用TaskPool。
【TaskPool和Worker的使用,未来如果有必要再展开讨论】
3、线程内通信
EventHub提供了线程内发送和处理事件的能力,包括对事件订阅、取消订阅、触发事件等。
在基类Context中提供了EventHub对象,可以通过发布订阅方式来实现事件的传递。在事件传递前,订阅者需要先进行订阅,当发布者发布事件时,订阅者将接收到事件并进行相应处理。
EventHub对象比较简单,主要提供了三个方法,如下:
// 订阅指定事件
on(event: string, callback: Function): void;
// 取消订阅事件
off(event: string, callback?: Function): void;
// 触发指定事件
emit(event: string, ...args: Object[]): void;
使用方法以UIAbility组件实例内通信为例:
👉🏻 step 1:
在UIAbility中调用eventHub.on()方法注册一个自定义事件“event1”,eventHub.on()有如下两种调用方式,使用其中一种即可(由于this指向问题,推荐使用箭头函数的方式注册)。
import { hilog } from '@kit.PerformanceAnalysisKit';
import { UIAbility, Context, Want, AbilityConstant } from '@kit.AbilityKit';
const DOMAIN_NUMBER: number = 0xFF00;
const TAG: string = '[EventAbility]';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// 获取eventHub
let eventhub = this.context.eventHub;
// 执行订阅操作
eventhub.on('event1', this.eventFunc);
eventhub.on('event1', (data: string) => {
// 触发事件,完成相应的业务操作
});
hilog.info(DOMAIN_NUMBER, TAG, '%{public}s', 'Ability onCreate');
}
// ...
eventFunc(argOne: Context, argTwo: Context): void {
hilog.info(DOMAIN_NUMBER, TAG, '1. ' + `${argOne}, ${argTwo}`);
return;
}
}
👉🏻 step 2:
在UI中通过eventHub.emit()方法触发该事件,在触发事件的同时,根据需要传入参数信息。
import { common } from '@kit.AbilityKit';
import { promptAction } from '@kit.ArkUI';
@Entry
@Component
struct Page_EventHub {
private context = getContext(this) as common.UIAbilityContext;
eventHubFunc(): void {
// 不带参数触发自定义“event1”事件
this.context.eventHub.emit('event1');
// 带1个参数触发自定义“event1”事件
this.context.eventHub.emit('event1', 1);
// 带2个参数触发自定义“event1”事件
this.context.eventHub.emit('event1', 2, 'test');
// 开发者可以根据实际的业务场景设计事件传递的参数
}
build() {
Column() {
// ...
List({ initialIndex: 0 }) {
ListItem() {
Row() {
// ...
}
.onClick(() => {
this.eventHubFunc();
promptAction.showToast({
message: 'EventHubFuncA'
});
})
}
// ...
ListItem() {
Row() {
// ...
}
.onClick(() => {
this.context.eventHub.off('event1');
promptAction.showToast({
message: 'EventHubFuncB'
});
})
}
// ...
}
// ...
}
// ...
}
}
👉🏻 step 3:
在自定义事件“event1”使用完成后,可以根据需要调用eventHub.off()方法取消该事件的订阅。
import { UIAbility } from '@kit.AbilityKit';
export default class EntryAbility extends UIAbility {
// ...
onDestroy(): void {
this.context.eventHub.off('event1');
}
}
示例中的代码,在UIAbility的注册事件回调中可以得到对应的触发事件结果,运行日志结果如下所示。
[Example].[Entry].[EntryAbility] 1. []
[Example].[Entry].[EntryAbility] 1. [1]
[Example].[Entry].[EntryAbility] 1. [2,"test"]