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

打印 上一主题 下一主题

主题 800|帖子 800|积分 2400

场景形貌

场景一:周期性任务处理,业务通过taskpool周期性处理业务。
场景二:延迟业务处理,业务一段时间后,通过taskpool处理业务。
场景三:串行业务处理,业务开展过程中,必要处理一系列的事务,事务处理过程中,存在先后次序。
场景四:业务的处理存在紧急优先次序,支持设置taskpool优先级处理。
场景五:ArkTS与Native协作开展业务,在ArkTS层触发业务,通过NAPI接口,通报到Native C++层,作业务管理等处理。
方案形貌

场景一:周期性任务

方案:
1)定时器判定周期性事务实行。
2)Taskpool来处理任务实行。

焦点代码:
  1. @Concurrent
  2. function ServiceHandle(pars: number): number {
  3.   hilog.info(0x0000, 'testTag', 'start ServiceHandle:%{public}d', pars);
  4.   // 业务处理过程,并将结果返回
  5.   let result = 0;
  6.   return result;
  7. }
  8. let count = 0;
  9. function TimerOutHandle(pars:number)
  10. {
  11.   count++;
  12.   let task: taskpool.Task = new taskpool.Task(ServiceHandle, pars);
  13.   hilog.info(0x0000, 'testTag', 'Timer handle count :%{public}d,pars %{public}d', count, pars);
  14.   taskpool.execute(task, taskpool.Priority.HIGH).then((res: object) => {
  15.     hilog.info(0x0000, 'testTag', 'ServiceHandle result :%{public}d', res);
  16.     if (g_callback != null) {
  17.       g_callback(count);
  18.     }
  19.   });
  20. }
  21. let timerId = -1;
  22. export function TimerTest()
  23. {
  24.   count = 0;
  25.   let value = 88;
  26.   timerId = setInterval(TimerOutHandle, 3000, value);
  27. }
复制代码
定时器每3秒超时一次,进入TimerOutHandle函数处理,TimerOutHandle函数体中,通过taskpool创建异步并发任务实行业务。
运行结果:

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

场景二:延迟任务

方案:
1)通过setTimeout来延迟处理。

  • 通过executeDelayed来延迟处理。
焦点代码:
1)setTimeout的处理如下:
  1. @Concurrent
  2. function ServiceHandle(pars: number): number {
  3.   hilog.info(0x0000, 'testTag', 'start ServiceHandle:%{public}d', pars);
  4.   // 业务处理过程,并将结果返回
  5.   let result = 0;
  6.   return result;
  7. }
  8. let count = 0;
  9. function TimerOutHandle(pars:number)
  10. {
  11.   count++;
  12.   let task: taskpool.Task = new taskpool.Task(ServiceHandle, pars);
  13.   hilog.info(0x0000, 'testTag', 'Timer handle count :%{public}d,pars %{public}d', count, pars);
  14.   taskpool.execute(task, taskpool.Priority.HIGH).then((res: object) => {
  15.     hilog.info(0x0000, 'testTag', 'ServiceHandle result :%{public}d', res);
  16.     if (g_callback != null) {
  17.       g_callback(count);
  18.     }
  19.   });
  20. }
  21. export function OneTimerCallTest()
  22. {
  23.   count = 0;
  24.   if (g_callback != null) {
  25.     g_callback(count);
  26.   }
  27.   let value = 99;
  28.   hilog.info(0x0000, 'testTag', 'start setTimeout');
  29.   timerId = setTimeout(TimerOutHandle, 3000, value);
  30. }
复制代码
定时器3秒超时(仅仅实行一次)后,就会进入TimerOutHandle函数处理,TimerOutHandle函数体中,通过taskpool创建异步并发任务实行业务。
2)executeDelayed来延迟
  1. @Concurrent
  2. function TaskDelayServiceHandle(pars: number): number {
  3.   let t: number = Date.now();
  4.   hilog.info(0x0000, 'testTag', 'enter TaskDelayServiceHandle, timer is :%{public}d', t);
  5.   // 业务处理过程,并将结果返回
  6.   let result = 0;
  7.   return result;
  8. }
  9. export function TaskPoolDelayTest()
  10. {
  11.   count = 0;
  12.   if (g_callback != null) {
  13.     g_callback(count);
  14.   }
  15.   let value = 100;
  16.   let t: number = Date.now();
  17.   hilog.info(0x0000, 'testTag', 'taskpool start time is :%{public}d', t);
  18.   let task: taskpool.Task = new taskpool.Task(TaskDelayServiceHandle, value);
  19.   taskpool.executeDelayed(3000, task).then(() => {
  20.     count++;
  21.     let t: number = Date.now();
  22.     hilog.info(0x0000, 'testTag', 'taskpool execute success, time is :%{public}d', t);
  23.     if (g_callback != null) {
  24.       g_callback(count);
  25.     }
  26.   }).catch((e: BusinessError) => {
  27.     console.error(`taskpool execute: Code: ${e.code}, message: ${e.message}`);
  28.   })
  29. }
复制代码
调用executeDelayed函数3秒后,会进入TaskDelayServiceHandle函数实行,返回返回后,会进入executeDelayed后面的then的函数体中实行。
运行结果:
1)利用setTimeout运行结果

2)利用executeDelayed运行结果

场景三:串行任务

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

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

焦点代码:
1)通过业务逻辑的结果来处理
  1. @Concurrent
  2. function ServiceHandle1(pars: number): number {
  3.   hilog.info(0x0000, 'testTag', 'start ServiceHandle1:%{public}d', pars);
  4.   // 业务处理过程,并将结果返回
  5.   let result = 0;
  6.   return result;
  7. }
  8. @Concurrent
  9. function ServiceHandle2(pars: number): number {
  10.   hilog.info(0x0000, 'testTag', 'start ServiceHandle2:%{public}d', pars);
  11.   // 业务处理过程,并将结果返回
  12.   let result = 1;
  13.   return result;
  14. }
  15. export function SyncHandle()
  16. {
  17.   let task1: taskpool.Task = new taskpool.Task(ServiceHandle1, 1);
  18.   hilog.info(0x0000, 'testTag', 'sync handle');
  19.   taskpool.execute(task1, taskpool.Priority.HIGH).then((res1: object) => {
  20.     hilog.info(0x0000, 'testTag', 'ServiceHandle result :%{public}d', res1);
  21.     if (g_callback != null) {
  22.       g_callback('task1 finish.');
  23.     }
  24.     if ((res1 as Number) == 0) {
  25.       let task2: taskpool.Task = new taskpool.Task(ServiceHandle2, 2);
  26.       taskpool.execute(task2, taskpool.Priority.HIGH).then((res2: object) => {
  27.         hilog.info(0x0000, 'testTag', 'ServiceHandle2 result :%{public}d', res2);
  28.         if (g_callback != null) {
  29.           g_callback('task2 finish.');
  30.         }
  31.       });
  32.     }
  33.   });
  34. }
复制代码
task1实行完毕后,根据if判定启动task2任务实行。
2)通过addDependency或SequenceRunner处理。
  1. @Concurrent
  2. function DependencyHandle(args: number): number {
  3.   let t: number = Date.now();
  4.   while ((Date.now() - t) < 1000) {
  5.     continue;
  6.   }
  7.   return args;
  8. }
  9. export function AddDependencyTest()
  10. {
  11.   let task1:taskpool.Task = new taskpool.Task(DependencyHandle, 100);
  12.   let task2:taskpool.Task = new taskpool.Task(DependencyHandle, 200);
  13.   let task3:taskpool.Task = new taskpool.Task(DependencyHandle, 300);
  14.   hilog.info(0x0000, 'testTag', 'dependency: add dependency start');
  15.   task1.addDependency(task2);
  16.   task2.addDependency(task3);
  17.   hilog.info(0x0000, 'testTag', 'dependency: add dependency end');
  18.   hilog.info(0x0000, 'testTag', 'dependency: start execute second');
  19.   taskpool.execute(task1).then(() => {
  20.     hilog.info(0x0000, 'testTag', 'dependency: first task1 success');
  21.     if (g_callback != null) {
  22.       g_callback('task1 finish.');
  23.     }
  24.   })
  25.   taskpool.execute(task2).then(() => {
  26.     hilog.info(0x0000, 'testTag', 'dependency: second task2 success');
  27.     if (g_callback != null) {
  28.       g_callback('task2 finish.');
  29.     }
  30.   })
  31.   taskpool.execute(task3).then(() => {
  32.     hilog.info(0x0000, 'testTag', 'dependency: third task3 success');
  33.     if (g_callback != null) {
  34.       g_callback('task3 finish.');
  35.     }
  36.   })
  37. }
复制代码
task1依靠task2,task2依靠task3,上面任务实行的顺序是:task3实行完毕后再实行task2,最后实行task。
  1. @Concurrent
  2. function additionDelay(delay:number): void {
  3.   let start: number = new Date().getTime();
  4.   while (new Date().getTime() - start < delay) {
  5.     continue;
  6.   }
  7. }
  8. @Concurrent
  9. function waitForRunner(finalString: string): string {
  10.   return finalString;
  11. }
  12. export async function SeqRunnerTest()
  13. {
  14.   let finalString:string = "";
  15.   let task1:taskpool.Task = new taskpool.Task(additionDelay, 3000);
  16.   let task2:taskpool.Task = new taskpool.Task(additionDelay, 2000);
  17.   let task3:taskpool.Task = new taskpool.Task(additionDelay, 1000);
  18.   let task4:taskpool.Task = new taskpool.Task(waitForRunner, finalString);
  19.   let runner:taskpool.SequenceRunner = new taskpool.SequenceRunner();
  20.   runner.execute(task1).then(() => {
  21.     finalString += 'task1 finish.';
  22.     hilog.info(0x0000, 'testTag', 'seqrunner: task1 done.');
  23.     if (g_callback != null) {
  24.       g_callback('task1 finish.');
  25.     }
  26.   });
  27.   runner.execute(task2).then(() => {
  28.     finalString += 'task2 finish.';
  29.     hilog.info(0x0000, 'testTag', 'seqrunner: task2 done.');
  30.     if (g_callback != null) {
  31.       g_callback('task2 finish.');
  32.     }
  33.   });
  34.   runner.execute(task3).then(() => {
  35.     finalString += 'task3 finish.';
  36.     hilog.info(0x0000, 'testTag', 'seqrunner: task3 done.');
  37.     if (g_callback != null) {
  38.       g_callback('task3 finish.');
  39.     }
  40.   });
  41.   await runner.execute(task4);
  42.   hilog.info(0x0000, 'testTag', 'seqrunner: task4 done, finalString is %{public}s', finalString);
  43. }
复制代码
task1实行完毕后,实行task2,最后是task3实行完毕。
运行结果:
1)通过业务逻辑的结果来处理

2)通过addDependency或SequenceRunner处理

场景四:优先级任务

方案:
在taskpool.execute的参数二种设置线程的优先级,优先级分三个级别:LOW、MEDIUM(默认)、HIGH。通过设置优先级来运行taskpool任务。
焦点代码:
  1. @Concurrent
  2. function ServiceHandle(pri: string): string {
  3.   hilog.info(0x0000, 'testTag', 'enter ServiceHandle:%{public}s', pri);
  4.   hilog.info(0x0000, 'testTag', 'end ServiceHandle:%{public}s', pri);
  5.   return pri;
  6. }
  7. export function CallPriorityHanel()
  8. {
  9.   let task1: taskpool.Task = new taskpool.Task(ServiceHandle, "LOW");
  10.   let task2: taskpool.Task = new taskpool.Task(ServiceHandle, "MEDIUM");
  11.   let task3: taskpool.Task = new taskpool.Task(ServiceHandle, "HIGH");
  12.   taskpool.execute(task1, taskpool.Priority.LOW).then((res: object) => {
  13.     hilog.info(0x0000, 'testTag', 'task return result :%{public}s', res);
  14.   });
  15.   taskpool.execute(task2, taskpool.Priority.MEDIUM).then((res: object) => {
  16.     hilog.info(0x0000, 'testTag', 'task return result :%{public}s', res);
  17.   });
  18.   taskpool.execute(task3, taskpool.Priority.HIGH).then((res: object) => {
  19.     hilog.info(0x0000, 'testTag', 'task return result :%{public}s', res);
  20.   });
  21. }
复制代码
当前的设备都是多核的,并不是说将优先级设置程HIGH,该任务就会最先调理。
运行结果:

场景五:taskpool的Napi调用
方案:C++层编译的库,在ArkTS层通过import库的方式引用后,在taskpool的回调函数中调用接口。焦点代码:
  1. @Concurrent
  2. function ServiceHandle(pars: number): number {
  3.   hilog.info(0x0000, 'testTag', 'start ServiceHandle:%{public}d', pars);
  4.   // 业务处理过程,并将结果返回
  5.   testNapi.jsServiceHandle(88, 99);
  6.   return 0;
  7. }
  8. export function CallHandle()
  9. {
  10.   let task: taskpool.Task = new taskpool.Task(ServiceHandle, 1);
  11.   taskpool.execute(task,).then((res: object) => {
  12.     hilog.info(0x0000, 'testTag', 'printArgs result :%{public}d', res);
  13.   });
  14. }
  15. typedef struct TestData {
  16.   int data;
  17.   int type;
  18. } TestData;
  19. static napi_value JsServiceHandle(napi_env env, napi_callback_info info)
  20. {
  21.   size_t argc = 2;
  22.   napi_value args[2] = {nullptr};
  23.   napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
  24.   TestData testData;
  25.   napi_get_value_int32(env, args[0], &testData.data);
  26.   napi_get_value_int32(env, args[1], &testData.type);
  27.   OH_LOG_INFO(LOG_APP, "Native C++ Service handle:%{public}d,type:%{public}d", testData.data, testData.type);
  28.   return nullptr;
  29. }
  30. EXTERN_C_START
  31. static napi_value Init(napi_env env, napi_value exports)
  32. {
  33.   napi_property_descriptor desc[] = {
  34.   {"jsServiceHandle", nullptr, JsServiceHandle, nullptr, nullptr, nullptr, napi_default, nullptr}
  35. };
  36. napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
  37. return exports;
  38. }
  39. EXTERN_C_END
复制代码
运行结果:

鸿蒙全栈开发全新学习指南

为了积极培养鸿蒙生态人才,让大家都能学习到鸿蒙开发最新的技能,针对一些在职人员、0基础小白、应届生/计算机专业、鸿蒙爱好者等人群,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技能的学习门路【包罗了大厂APP实战项目开发】
本门路共分为四个阶段:

第一阶段:鸿蒙初中级开发必备技能


第二阶段:鸿蒙南北双向高工技能基础:gitee.com/MNxiaona/733GH


第三阶段:应用开发中高级就业技能


第四阶段:全网首发-工业级南向设备开发就业技能:gitee.com/MNxiaona/733GH


《鸿蒙 (Harmony OS)开发学习手册》(共计892页)

如何快速入门?

1.根本概念
2.构建第一个ArkTS应用
3.……

开发基础知识:gitee.com/MNxiaona/733GH

1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

基于ArkTS 开发

1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.背景任务(Background Task)管理
11.设备管理
12.设备利用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

鸿蒙开发口试真题(含参考答案):gitee.com/MNxiaona/733GH


鸿蒙入门讲授视频:


美团APP实战开发讲授:gitee.com/MNxiaona/733GH


写在最后



  • 假如你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以等待后续文章ing

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

冬雨财经

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表