HarmonyOS 开发实践——基于Taskpool的多线程操作

场景描述

场景一:周期性任务处理,业务通过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来延迟处理。

2) 通过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

运行结果:

阅读全文
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.1024c.cn/archives/21965,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?