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

544 篇文章 5 订阅
433 篇文章 3 订阅

场景描述

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

方案描述

场景一:周期性任务

方案:

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

2)Taskpool来处理任务执行。

核心代码:

@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来延迟处理。

  1. 通过executeDelayed来延迟处理。

核心代码:

1)setTimeout的处理如下:

@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来延迟

@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)通过业务逻辑的结果来处理

@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处理。

@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。

@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任务。

核心代码:

@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的回调函数中调用接口。核心代码:

@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

运行结果:

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

之前总有很多小伙伴向我反馈说,不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以这里为大家准备了一份实用的鸿蒙(HarmonyOS NEXT)学习路线与学习文档用来跟着学习是非常有必要的。

针对一些列因素,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:https://qr21.cn/FV7h05

如何快速入门:

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

开发基础知识:https://qr21.cn/FV7h05

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

基于ArkTS 开发:https://qr21.cn/FV7h05

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

鸿蒙开发面试真题(含参考答案):https://qr21.cn/FV7h05

大厂鸿蒙面试题::https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值