【鸿蒙实战开发】基于Taskpool的多线程操作

场景描述

场景一:周期性任务处理,业务通过taskpool周期性处理业务。

场景二:延迟业务处理,业务一段时间后,通过taskpool处理业务。

场景三:串行业务处理,业务开展过程中,需要处理一系列的事务,事务处理过程中,存在先后次序。

场景四:业务的处理存在紧急优先次序,支持设置taskpool优先级处理。

场景五:ArkTS与Native协作开展业务,在ArkTS层触发业务,通过NAPI接口,传递到Native C++层,作业务管理等处理。

方案描述

场景一:周期性任务

方案:

1)定时器判断周期性事务执行。

2)Taskpool来处理任务执行。

核心代码:

text
复制代码
@Concurrent function ServiceHandle(pars: number): number {   hilog.info(0x0000, 'testTag', 'start ServiceHandle:%{public}d', pars);   // 业务处理过程,并将结果返回   let result = 0;   return result; } let count = 0; function TimerOutHandle(pars:number) {   count++;   let task: taskpool.Task = new taskpool.Task(ServiceHandle, pars);   hilog.info(0x0000, 'testTag', 'Timer handle count :%{public}d,pars %{public}d', count, pars);   taskpool.execute(task, taskpool.Priority.HIGH).then((res: object) => {     hilog.info(0x0000, 'testTag', 'ServiceHandle result :%{public}d', res);     if (g_callback != null) {       g_callback(count);     }   }); } let timerId = -1; export function TimerTest() {   count = 0;   let value = 88;   timerId = setInterval(TimerOutHandle, 3000, value); }

定时器每3秒超时一次,进入TimerOutHandle函数处理,TimerOutHandle函数体中,通过taskpool创建异步并发任务执行业务。

运行结果:

界面上,每超时一次,会呈现运行次数:

场景二:延迟任务

方案:

1)通过setTimeout来延迟处理。

2) 通过executeDelayed来延迟处理。

核心代码:

1)setTimeout的处理如下:

text
复制代码
@Concurrent function ServiceHandle(pars: number): number {   hilog.info(0x0000, 'testTag', 'start ServiceHandle:%{public}d', pars);   // 业务处理过程,并将结果返回   let result = 0;   return result; } let count = 0; function TimerOutHandle(pars:number) {   count++;   let task: taskpool.Task = new taskpool.Task(ServiceHandle, pars);   hilog.info(0x0000, 'testTag', 'Timer handle count :%{public}d,pars %{public}d', count, pars);   taskpool.execute(task, taskpool.Priority.HIGH).then((res: object) => {     hilog.info(0x0000, 'testTag', 'ServiceHandle result :%{public}d', res);     if (g_callback != null) {       g_callback(count);     }   }); } export function OneTimerCallTest() {   count = 0;   if (g_callback != null) {     g_callback(count);   }   let value = 99;   hilog.info(0x0000, 'testTag', 'start setTimeout');   timerId = setTimeout(TimerOutHandle, 3000, value); }

定时器3秒超时(仅仅执行一次)后,就会进入TimerOutHandle函数处理,TimerOutHandle函数体中,通过taskpool创建异步并发任务执行业务。

2)executeDelayed来延迟

text
复制代码
@Concurrent function TaskDelayServiceHandle(pars: number): number {   let t: number = Date.now();   hilog.info(0x0000, 'testTag', 'enter TaskDelayServiceHandle, timer is :%{public}d', t);   // 业务处理过程,并将结果返回   let result = 0;   return result; } export function TaskPoolDelayTest() {   count = 0;   if (g_callback != null) {     g_callback(count);   }   let value = 100;   let t: number = Date.now();   hilog.info(0x0000, 'testTag', 'taskpool start time is :%{public}d', t);   let task: taskpool.Task = new taskpool.Task(TaskDelayServiceHandle, value);   taskpool.executeDelayed(3000, task).then(() => {     count++;     let t: number = Date.now();     hilog.info(0x0000, 'testTag', 'taskpool execute success, time is :%{public}d', t);     if (g_callback != null) {       g_callback(count);     }   }).catch((e: BusinessError) => {     console.error(`taskpool execute: Code: ${e.code}, message: ${e.message}`);   }) }

调用executeDelayed函数3秒后,会进入TaskDelayServiceHandle函数执行,返回返回后,会进入executeDelayed后面的then的函数体中执行。

运行结果:

1)使用setTimeout运行结果

2)使用executeDelayed运行结果

场景三:串行任务

方案:

1)最简单的方案就是后面任务执行时,根据前面任务的执行结果来处理。

2)后面任务的执行,依赖另一个任务的一些处理结果后,继续执行。

核心代码:

1)通过业务逻辑的结果来处理

text
复制代码
@Concurrent function ServiceHandle1(pars: number): number {   hilog.info(0x0000, 'testTag', 'start ServiceHandle1:%{public}d', pars);   // 业务处理过程,并将结果返回   let result = 0;   return result; } @Concurrent function ServiceHandle2(pars: number): number {   hilog.info(0x0000, 'testTag', 'start ServiceHandle2:%{public}d', pars);   // 业务处理过程,并将结果返回   let result = 1;   return result; } export function SyncHandle() {   let task1: taskpool.Task = new taskpool.Task(ServiceHandle1, 1);   hilog.info(0x0000, 'testTag', 'sync handle');   taskpool.execute(task1, taskpool.Priority.HIGH).then((res1: object) => {     hilog.info(0x0000, 'testTag', 'ServiceHandle result :%{public}d', res1);     if (g_callback != null) {       g_callback('task1 finish.');     }     if ((res1 as Number) == 0) {       let task2: taskpool.Task = new taskpool.Task(ServiceHandle2, 2);       taskpool.execute(task2, taskpool.Priority.HIGH).then((res2: object) => {         hilog.info(0x0000, 'testTag', 'ServiceHandle2 result :%{public}d', res2);         if (g_callback != null) {           g_callback('task2 finish.');         }       });     }   }); }

task1执行完毕后,根据if判断启动task2任务执行。

2)通过addDependency或SequenceRunner处理。

text
复制代码
@Concurrent function DependencyHandle(args: number): number {   let t: number = Date.now();   while ((Date.now() - t) < 1000) {     continue;   }   return args; } export function AddDependencyTest() {   let task1:taskpool.Task = new taskpool.Task(DependencyHandle, 100);   let task2:taskpool.Task = new taskpool.Task(DependencyHandle, 200);   let task3:taskpool.Task = new taskpool.Task(DependencyHandle, 300);   hilog.info(0x0000, 'testTag', 'dependency: add dependency start');   task1.addDependency(task2);   task2.addDependency(task3);   hilog.info(0x0000, 'testTag', 'dependency: add dependency end');   hilog.info(0x0000, 'testTag', 'dependency: start execute second');   taskpool.execute(task1).then(() => {     hilog.info(0x0000, 'testTag', 'dependency: first task1 success');     if (g_callback != null) {       g_callback('task1 finish.');     }   })   taskpool.execute(task2).then(() => {     hilog.info(0x0000, 'testTag', 'dependency: second task2 success');     if (g_callback != null) {       g_callback('task2 finish.');     }   })   taskpool.execute(task3).then(() => {     hilog.info(0x0000, 'testTag', 'dependency: third task3 success');     if (g_callback != null) {       g_callback('task3 finish.');     }   }) }

task1依赖task2,task2依赖task3,上面任务执行的顺序是:task3执行完毕后再执行task2,最后执行task。

text
复制代码
@Concurrent function additionDelay(delay:number): void {   let start: number = new Date().getTime();   while (new Date().getTime() - start < delay) {     continue;   } } @Concurrent function waitForRunner(finalString: string): string {   return finalString; } export async function SeqRunnerTest() {   let finalString:string = "";   let task1:taskpool.Task = new taskpool.Task(additionDelay, 3000);   let task2:taskpool.Task = new taskpool.Task(additionDelay, 2000);   let task3:taskpool.Task = new taskpool.Task(additionDelay, 1000);   let task4:taskpool.Task = new taskpool.Task(waitForRunner, finalString);   let runner:taskpool.SequenceRunner = new taskpool.SequenceRunner();   runner.execute(task1).then(() => {     finalString += 'task1 finish.';     hilog.info(0x0000, 'testTag', 'seqrunner: task1 done.');     if (g_callback != null) {       g_callback('task1 finish.');     }   });   runner.execute(task2).then(() => {     finalString += 'task2 finish.';     hilog.info(0x0000, 'testTag', 'seqrunner: task2 done.');     if (g_callback != null) {       g_callback('task2 finish.');     }   });   runner.execute(task3).then(() => {     finalString += 'task3 finish.';     hilog.info(0x0000, 'testTag', 'seqrunner: task3 done.');     if (g_callback != null) {       g_callback('task3 finish.');     }   });   await runner.execute(task4);   hilog.info(0x0000, 'testTag', 'seqrunner: task4 done, finalString is %{public}s', finalString); }

task1执行完毕后,执行task2,最后是task3执行完毕。

运行结果:

1)通过业务逻辑的结果来处理

2)通过addDependency或SequenceRunner处理

场景四:优先级任务

方案:

在taskpool.execute的参数二种设置线程的优先级,优先级分三个级别:LOW、MEDIUM(默认)、HIGH。通过设置优先级来运行taskpool任务。

核心代码:

text
复制代码
@Concurrent function ServiceHandle(pri: string): string {   hilog.info(0x0000, 'testTag', 'enter ServiceHandle:%{public}s', pri);   hilog.info(0x0000, 'testTag', 'end ServiceHandle:%{public}s', pri);   return pri; } export function CallPriorityHanel() {   let task1: taskpool.Task = new taskpool.Task(ServiceHandle, "LOW");   let task2: taskpool.Task = new taskpool.Task(ServiceHandle, "MEDIUM");   let task3: taskpool.Task = new taskpool.Task(ServiceHandle, "HIGH");   taskpool.execute(task1, taskpool.Priority.LOW).then((res: object) => {     hilog.info(0x0000, 'testTag', 'task return result :%{public}s', res);   });   taskpool.execute(task2, taskpool.Priority.MEDIUM).then((res: object) => {     hilog.info(0x0000, 'testTag', 'task return result :%{public}s', res);   });   taskpool.execute(task3, taskpool.Priority.HIGH).then((res: object) => {     hilog.info(0x0000, 'testTag', 'task return result :%{public}s', res);   }); }

当前的设备都是多核的,并不是说将优先级设置程HIGH,该任务就会最先调度。

运行结果:

场景五:taskpool的Napi调用

方案:C++层编译的库,在ArkTS层通过import库的方式引用后,在taskpool的回调函数中调用接口。核心代码:

text
复制代码
@Concurrent function ServiceHandle(pars: number): number {   hilog.info(0x0000, 'testTag', 'start ServiceHandle:%{public}d', pars);   // 业务处理过程,并将结果返回   testNapi.jsServiceHandle(88, 99);   return 0; } export function CallHandle() {   let task: taskpool.Task = new taskpool.Task(ServiceHandle, 1);   taskpool.execute(task,).then((res: object) => {     hilog.info(0x0000, 'testTag', 'printArgs result :%{public}d', res);   }); } typedef struct TestData {   int data;   int type; } TestData; static napi_value JsServiceHandle(napi_env env, napi_callback_info info) {   size_t argc = 2;   napi_value args[2] = {nullptr};   napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);   TestData testData;   napi_get_value_int32(env, args[0], &testData.data);   napi_get_value_int32(env, args[1], &testData.type);   OH_LOG_INFO(LOG_APP, "Native C++ Service handle:%{public}d,type:%{public}d", testData.data, testData.type);   return nullptr; } EXTERN_C_START static napi_value Init(napi_env env, napi_value exports) {   napi_property_descriptor desc[] = {   {"jsServiceHandle", nullptr, JsServiceHandle, nullptr, nullptr, nullptr, napi_default, nullptr} }; napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); return exports; } EXTERN_C_END

运行结果:

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
下载 APP