使用Worker创建线程
- 基本概念:Worker主要为应用程序提供多线程运行环境,可让应用程序在执行过程中与宿主线程分离,在后台线程中运行脚本进行耗时操作,避免计算密集型或高延迟任务阻塞宿主线程。
- 使用方法:
- 创建Worker线程文件:Worker线程文件需要放在
{moduleName}/src/main/ets/
目录层级之下。可以手动创建相关目录及文件,并配置build-profile.json5
的相关字段信息;也可以使用DevEco Studio一键生成Worker,自动生成模板文件及配置信息。
- 构造Worker实例:根据不同的API版本和模型,使用相应的构造函数传入Worker线程文件的路径来创建
worker.ThreadWorker
或worker.Worker
实例。例如,在API 9及之后版本的Stage模型下,如果worker
线程文件所在路径为"entry/src/main/ets/workers/worker.ets"
,则可以这样创建:const workerStage1: worker.ThreadWorker = new worker.ThreadWorker('entry/ets/workers/worker.ets');
- 通信与任务执行:在宿主线程和Worker子线程中通过
onmessage
和postMessage
方法进行消息传递,以实现数据交互和任务执行。
- 注意事项:
- 需要手动管理Worker的生命周期,且最多同时运行的Worker子线程数量为64个。当不需要Worker时,应调用
terminate()
接口或close()
方法主动销毁Worker,避免资源浪费。
- 使用Worker模块时,需要在宿主线程中注册
onerror
接口,否则当Worker线程出现异常时会发生jscrash
问题。
- 不支持跨HAP使用Worker线程文件,引用HAR/HSP前,需要先配置对HAR/HSP的依赖。
使用TaskPool创建线程
- 基本概念:TaskPool为应用程序提供多线程运行环境,能降低资源消耗、提升系统性能,开发者无需关心线程实例的生命周期。它支持在宿主线程封装任务并抛给任务队列,系统会选择合适的工作线程进行任务分发与执行,并将结果返回给宿主线程。
- 使用方法:
- 定义任务函数:使用
@Concurrent
装饰器标注要在任务池中执行的函数。该装饰器从API version 9开始支持,仅在Stage模型的工程中的.ets
文件中使用。被装饰的函数可以是async
函数或普通函数,但禁止是generator
、箭头函数、类方法,也不支持类成员函数或者匿名函数。函数内允许使用local
变量、入参和通过import
引入的变量,禁止使用闭包变量。
- 创建任务并执行:在需要执行并发任务的地方,创建
taskpool.Task
对象,将定义好的任务函数作为参数传入,并通过taskpool.execute
方法执行任务。例如:
import { taskpool } from '@kit.ArkTS';
@Concurrent
function add(num1: number, num2: number): number {
return num1 + num2;
}
async function ConcurrentFunc(): Promise<void> {
try {
let task: taskpool.Task = new taskpool.Task(add, 1, 2);
console.info("taskpool res is: " + await taskpool.execute(task));
} catch (e) {
console.error("taskpool execute error is: " + e);
}
}
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
ConcurrentFunc();
})
}
.width('100%')
}
.height('100%')
}
}
- 注意事项:
- 任务函数在TaskPool工作线程的执行耗时不能超过3分钟(不包含
Promise
和async/await
异步调用的耗时,例如网络下载、文件读写等I/O任务的耗时),否则会被强制退出。
- 实现任务的函数入参需满足序列化支持的类型。
ArrayBuffer
参数在TaskPool中默认转移,需要设置转移列表的话可通过接口setTransferList()
设置。
- 从API version 11开始,跨并发实例传递带方法的实例对象时,该类必须使用
@Sendable
装饰器标注,且仅支持在.ets
文件中使用。
通过NAPI机制在C代码中使用标准线程API创建线程
- 基本概念:通过NAPI(Native API)机制,可以在C代码中使用标准的线程API来创建线程,直接利用操作系统提供的线程创建和管理功能,实现更底层的线程控制。
- 使用方法:通常使用
pthread_create
函数来创建线程,其函数原型为int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
。例如:
#include <pthread.h>
void *CreateArkRuntimeFunc(void *arg) {
return NULL;
}
int main() {
pthread_t tid;
pthread_create(&tid, nullptr, CreateArkRuntimeFunc, nullptr);
pthread_join(tid, NULL);
return 0;
}