鸿蒙多线程开发——同步任务处理

1、概 述

目前,多线程的开发我们已经学过TaskPool和Worker两种方式:

我们现在讨论下多线程的同步任务处理。

同步任务是指在多个线程之间协调执行的任务,其目的是确保多个任务按照一定的顺序和规则执行,例如使用锁来防止数据竞争。

由于TaskPool偏向于单个独立的任务,因此当各个同步任务之间相对独立时推荐使用TaskPool,例如一系列导入的静态方法,或者单例实现的方法。如果同步任务之间有关联性,则需要使用Worker,例如无法单例创建的类对象实现的方法。

2、Worker处理关联的同步任务

当一系列同步任务需要使用同一个句柄调度,或者需要依赖某个统一调度管理的类,而这些类或者句柄无法在不同任务池之间共享时,我们需要使用Worker。

👉🏻 step 1

 在主线程中创建Worker对象,同时接收Worker线程发送回来的消息,根据实际的业务场景,再发送对应的指令到worker中。

// Index.etsimport { worker } from '@kit.ArkTS';@Entry@Componentstruct Index {  @State message: string = 'Hello World';  build() {    Row() {      Column() {        Text(this.message)          .fontSize(50)          .fontWeight(FontWeight.Bold)          .onClick(() => {            let w: worker.ThreadWorker = new worker.ThreadWorker('entry/ets/workers/MyWorker.ts');            w.onmessage = (): void => {              // 接收Worker子线程的结果            }            w.onerror = (): void => {              // 接收Worker子线程的错误信息            }            // 向Worker子线程发送Set消息            w.postMessage({'type': 0, 'data': 'data'})            // 向Worker子线程发送Get消息            w.postMessage({'type': 1})            // ...            // 根据实际业务,选择时机以销毁线程            w.terminate()          })      }      .width('100%')    }    .height('100%')  }}

👉🏻 step 2

在Worker线程中绑定Worker对象,同时处理同步任务逻辑。

// handle.ts代码export default class Handle {  syncGet() {    return;  }  syncSet(num: number) {    return;  }}// MyWorker.ts代码import { worker, ThreadWorkerGlobalScope, MessageEvents } from '@kit.ArkTS';import Handle from './handle';  // 返回句柄let workerPort : ThreadWorkerGlobalScope = worker.workerPort;// 无法传输的句柄,所有操作依赖此句柄let handler: Handle = new Handle()// Worker线程的onmessage逻辑workerPort.onmessage = (e : MessageEvents): void => { switch (e.data.type as number) {  case 0:   handler.syncSet(e.data.data);   workerPort.postMessage('success set');   break;  case 1:   handler.syncGet();   workerPort.postMessage('success get');   break; }}

3、TaskPool处理同步任务

当调度独立的任务为静态方法实现,或者可以通过单例构造唯一的句柄或类对象,可在不同任务线程之间使用时,推荐使用TaskPool。

👉🏻 step 1

模拟一个包含同步调用的单例(注意:第二行中的 "use shared" )。​​​​​​​

// Handle.ets 代码"use shared"@Sendableexport default class Handle {  private static instance: Handle = new Handle();  static getInstance(): Handle {    // 返回单例对象    return Handle.instance;  }  static syncGet(): void {    // 同步Get方法  }  static syncSet(num: number): number {    // 模拟同步步骤1    console.info("taskpool: this is 1st print!");    // 模拟同步步骤2    console.info("taskpool: this is 2nd print!");    return ++num;  }  static syncSet2(num: number): number {    // 模拟同步步骤1    console.info("taskpool: this is syncSet2 1st print!");    // 模拟同步步骤2    console.info("taskpool: this is syncSet2 2nd print!");    return ++num;  }}

👉🏻 step 2

  1. 定义并发函数func【必须使用@Concurrent装饰器装饰该函数】;

  2. 定义函数asyncGet,该函数功能为创建多线程任务,执行对应任务并打印其返回的结果;

  3. 最后在主线程调用函数asyncGet。

// Index.ets代码import { taskpool} from '@kit.ArkTS';import Handle from './Handle'; // 返回静态句柄// 步骤1: 定义并发函数,内部调用同步方法@Concurrentasync function func(num: number): Promise<number> {  // 调用静态类对象中实现的同步等待调用  // 先调用syncSet方法并将其结果作为syncSet2的参数,模拟同步调用逻辑  let tmpNum: number = Handle.syncSet(num);  console.info("this is Child_Thread")  return Handle.syncSet2(tmpNum);}// 步骤2: 创建任务并执行async function asyncGet(): Promise<void> {  // 创建task、task2并传入函数func  let task: taskpool.Task = new taskpool.Task(func, 1);  let task2: taskpool.Task = new taskpool.Task(func, 2);  // 执行task、task2任务,await保证其同步执行  let res: number = await taskpool.execute(task) as number;  let res2: number = await taskpool.execute(task2) as number;  // 打印任务结果  console.info("taskpool: task res is: " + res);  console.info("taskpool: task res2 is: " + res2);}@Entry@Componentstruct Index {  @State message: string = 'Hello World';  build() {    Row() {      Column() {        Text(this.message)          .fontSize(50)          .fontWeight(FontWeight.Bold)          .onClick(async () => {            // 步骤3: 执行并发操作            asyncGet();            let num: number = Handle.syncSet(100);            console.info("this is Main_Thread!")          })      }      .width('100%')      .height('100%')    }  }}

日志打印如下:

图片

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值