TaskPool简单使用
关注“极客马拉松”, 回复“仓库”查看更多代码 概述 任务池(taskpool)作用是为应用程序提供一个多线程的运行环境,降低整体资源的消耗、提高系统的整体性能,且您无需关心线程实例的生命周期。您可以使用任务池API创建后台任务(Task),并对所创建的任务进行如任务执行、任务取消的操作。理论上您可以使用任务池API创建数量不受限制的任务,但是出于内存因素不建议您这样做。此外,不建议您在任务中执行阻塞操作,特别是无限期阻塞操作,长时间的阻塞操作占据工作线程,可能会阻塞其他任务调度,影响您的应用性能。
方法 taskPool.execute 将创建好的任务放入taskpool内部任务队列,任务不会立即执行,而是等待分发到工作线程执行。 execute(task: Task, priority?: Priority): Promise execute(group: TaskGroup, priority?: Priority): Promise<Object[]>
taskPool.cancel 取消任务池中的任务组。当一个任务组的任务未全部执行结束时取消任务组,返回undefined作为任务组结果。
Task 表示任务。使用constructor方法构造Task。任务可以多次执行或放入任务组执行或放入串行队列执行或添加依赖关系执行。
constructor(name: string, func: Function, ...args: Object[]) Task的构造函数,可以指定任务名称。
static sendData(...args: Object[]): void 在任务执行过程中向宿主线程发送消息并触发回调。使用该方法前需要先构造Task。 ● 该接口在taskpool的线程中调用。 ● 避免在回调函数中使用该方法。 ● 调用该接口时确保处理数据的回调函数在宿主线程已注册。
onReceiveData(callback?: Function): void 为任务注册回调函数,以接收和处理来自任务池工作线程的数据。使用该方法前需要先构造Task。 不支持给同一个任务定义多种回调函数,如果重复赋值只有最后一个会生效。
terminateTask(longTask: LongTask): void 中止任务池中的长时任务,在长时任务执行完成后调用。中止后,执行长时任务的线程可能会被回收。
TaskGroup 表示任务组,一次执行一组任务,适用于执行一组有关联的任务。如果所有任务正常执行,异步执行完毕后返回所有任务结果的数组,数组中元素的顺序与addTask的顺序相同; addTask(func: Function, ...args: Object[]): void 将待执行的函数添加到任务组中。使用该方法前需要先构造TaskGroup。 LongTask 表示长时任务。LongTask继承自Task。 长时任务不设置执行时间上限,长时间运行不会触发超时异常,但不支持在任务组(TaskGroup)执行和多次执行。 执行长时任务的线程一直存在,直到执行完成后调用terminateTask,该线程会在空闲时被回收。
- lettask: taskpool.LongTask = new taskpool.LongTask(printArgs, "this is my first LongTask");
实践 创建三个线程,配合异步锁,对同一份数据进行减法操作。 注:这部分代码十分重要,只可意会,不可言传。主要在异步运行的时间片要位于同一位置。 while ((res = await a.down()) > 0) { taskpool.Task.sendData(name, res) console.info(name + " :InputModule: count is:" + res); }
/*
* Sendable对象为可共享的,其跨线程前后指向同一个JS对象。
* 当多个并发实例尝试同时更新Sendable数据时,会发生数据竞争,例如ArkTS共享容器的多线程操作。
* 因此,ArkTS提供了异步锁的机制来避免不同并发实例间的数据竞争。
* 同时,还可以通过对象冻结接口冻结对象,将其变为只读对象,就可以不用考虑数据的竞争问题。
*
* 为了解决多线程并发任务间的数据竞争问题,ArkTS引入了异步锁能力。
* 异步锁可能会被类对象持有,因此为了更方便地在并发实例间获取同一个异步锁对象,AsyncLock对象支持跨线程引用传递。
* 使用异步锁的方法需要标记为async,调用方需要使用await修饰,才能保证时序正确。
* */
@Sendable
export class TestModel {
//异步锁
lock_: ArkTSUtils.locks.AsyncLock = new ArkTSUtils.locks.AsyncLock()
private num: number = 1000
public async down() {
await this.lock_.lockAsync(() => {
this.num--
})
}
public async getNum() : Promise<number> {
return await this.lock_.lockAsync(() => {
return this.num
});
}
}