線程模型
FA模型下的線程主要有如下三類:
- 主線程: 負責(zé)管理其他線程。
- Ability線程:
- 每個Ability一個線程。
- 輸入事件分發(fā)。
- UI繪制。
- 應(yīng)用代碼回調(diào)(事件處理,生命周期)。
- 接收Worker發(fā)送的消息。
- Worker線程: 執(zhí)行耗時操作。
基于當前的線程模型,不同的業(yè)務(wù)功能運行在不同的線程上,業(yè)務(wù)功能的交互就需要線程間通信。線程間通信目前主要有[Emitter]
開發(fā)前請熟悉鴻蒙開發(fā)指導(dǎo)文檔 :[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md
]
使用Emitter進行線程間通信
[Emitter]主要提供線程間發(fā)送和處理事件的能力,包括對持續(xù)訂閱事件或單次訂閱事件的處理、取消訂閱事件、發(fā)送事件到事件隊列等。
Emitter的開發(fā)步驟如下:
訂閱事件
import emitter from '@ohos.events.emitter'; import promptAction from '@ohos.promptAction'; import hilog from '@ohos.hilog'; const TAG: string = 'ThreadModel'; const DOMAIN_NUMBER: number = 0xFF00;
// 定義一個eventId為1的事件 let event: emitter.InnerEvent = { eventId: 1 }; // 收到eventId為1的事件后執(zhí)行該回調(diào) let callback = (eventData: emitter.EventData): void = > { promptAction.showToast({ message: JSON.stringify(eventData) }); hilog.info(DOMAIN_NUMBER, TAG, 'event callback:' + JSON.stringify(eventData)); }; // 訂閱eventId為1的事件 emitter.on(event, callback); promptAction.showToast({ message: $r('app.string.emitter_subscribe_success_toast') });
發(fā)送事件
import emitter from '@ohos.events.emitter';
// 定義一個eventId為1的事件,事件優(yōu)先級為Low let event: emitter.InnerEvent = { eventId: 1, priority: emitter.EventPriority.LOW }; let eventData: emitter.EventData = { data: { content: 'c', id: 1, isEmpty: false } }; // 發(fā)送eventId為1的事件,事件內(nèi)容為eventData emitter.emit(event, eventData);
[Worker]兩種方式,其中Emitter主要適用于線程間的事件同步, Worker主要用于新開一個線程執(zhí)行耗時任務(wù)。
Worker簡介
Worker主要作用是為應(yīng)用程序提供一個多線程的運行環(huán)境,可滿足應(yīng)用程序在執(zhí)行過程中與主線程分離,在后臺線程中運行一個腳本操作耗時操作,極大避免類似于計算密集型或高延遲的任務(wù)阻塞主線程的運行。具體接口信息及使用方法詳情請見[Worker]。
Worker運作機制
圖1 Worker運作機制示意圖
創(chuàng)建Worker的線程稱為宿主線程(不一定是主線程,工作線程也支持創(chuàng)建Worker子線程),Worker自身的線程稱為Worker子線程(或Actor線程、工作線程)。每個Worker子線程與宿主線程擁有獨立的實例,包含基礎(chǔ)設(shè)施、對象、代碼段等。Worker子線程和宿主線程之間的通信是基于消息傳遞的,Worker通過序列化機制與宿主線程之間相互通信,完成命令及數(shù)據(jù)交互。
Worker注意事項
- 創(chuàng)建Worker時,有手動和自動兩種創(chuàng)建方式,手動創(chuàng)建Worker線程目錄及文件時,還需同步進行相關(guān)配置,詳情請參考[創(chuàng)建Worker的注意事項]。
- 使用Worker能力時,構(gòu)造函數(shù)中傳入的Worker線程文件的路徑在不同版本有不同的規(guī)則,詳情請參見[文件路徑注意事項]。
- Worker創(chuàng)建后需要手動管理生命周期,且最多同時運行的Worker子線程數(shù)量為64個,詳情請參見[生命周期注意事項]。
- 由于不同線程中上下文對象是不同的,因此Worker線程只能使用線程安全的庫,例如UI相關(guān)的非線程安全庫不能使用,具體請見[多線程安全注意事項]。
- 序列化傳輸?shù)臄?shù)據(jù)量大小限制為16MB。
- 使用Worker模塊時,需要在主線程中注冊onerror接口,否則當worker線程出現(xiàn)異常時會發(fā)生jscrash問題。
- 不支持跨HAP使用Worker線程文件。
創(chuàng)建Worker的注意事項
Worker線程文件需要放在"{moduleName}/src/main/ets/"目錄層級之下,否則不會被打包到應(yīng)用中。有手動和自動兩種創(chuàng)建Worker線程目錄及文件的方式。
手動創(chuàng)建:開發(fā)者手動創(chuàng)建相關(guān)目錄及文件,此時需要配置build-profile.json5的相關(guān)字段信息,Worker線程文件才能確保被打包到應(yīng)用中。
Stage模型:"buildOption": { "sourceOption": { "workers": [ "./src/main/ets/workers/worker.ets" ] } }
FA模型:
"buildOption": { "sourceOption": { "workers": [ "./src/main/ets/MainAbility/workers/worker.ets" ] } }
自動創(chuàng)建:DevEco Studio支持一鍵生成Worker,在對應(yīng)的{moduleName}目錄下任意位置, 點擊鼠標右鍵 > New > Worker ,即可自動生成Worker的模板文件及配置信息,無需再手動在build-profile.json5中進行相關(guān)配置。
文件路徑注意事項
當使用Worker模塊具體功能時,均需先構(gòu)造Worker實例對象,其構(gòu)造函數(shù)與API版本相關(guān),且構(gòu)造函數(shù)需要傳入Worker線程文件的路徑(scriptURL)。
// 導(dǎo)入模塊
import { worker } from '@kit.ArkTS';
// API 9及之后版本使用:
const worker1: worker.ThreadWorker = new worker.ThreadWorker('entry/ets/workers/MyWorker.ets');
// API 8及之前版本使用:
const worker2: worker.Worker = new worker.Worker('entry/ets/workers/MyWorker.ets');
Stage模型下的文件路徑規(guī)則
構(gòu)造函數(shù)中的scriptURL要求如下:
- scriptURL的組成包含 {moduleName}/ets 和相對路徑 relativePath。
- relativePath是Worker線程文件和"{moduleName}/src/main/ets/"目錄的相對路徑。
1) 加載Ability中Worker線程文件場景
加載Ability中的worker線程文件,加載路徑規(guī)則:{moduleName}/ets/{relativePath}。
import { worker } from '@kit.ArkTS';
// worker線程文件所在路徑:"entry/src/main/ets/workers/worker.ets"
const workerStage1: worker.ThreadWorker = new worker.ThreadWorker('entry/ets/workers/worker.ets');
// worker線程文件所在路徑:"phone/src/main/ets/ThreadFile/workers/worker.ets"
const workerStage2: worker.ThreadWorker = new worker.ThreadWorker('phone/ets/ThreadFile/workers/worker.ets');
2) 加載Library-[HSP]中Worker線程文件場景
加載HSP中worker線程文件,加載路徑規(guī)則:{moduleName}/ets/{relativePath}。
import { worker } from '@kit.ArkTS';
// worker線程文件所在路徑: "hsp/src/main/ets/workers/worker.ets"
const workerStage3: worker.ThreadWorker = new worker.ThreadWorker('hsp/ets/workers/worker.ets');
3) 加載Library-[HAR]中Worker線程文件場景
加載HAR中worker線程文件存在以下兩種情況:
- @標識路徑加載形式:所有種類的模塊加載本地HAR中的Worker線程文件,加載路徑規(guī)則:@{moduleName}/ets/{relativePath}。
- 相對路徑加載形式:本地HAR加載該包內(nèi)的Worker線程文件,加載路徑規(guī)則:創(chuàng)建Worker對象所在文件與Worker線程文件的相對路徑。
需要注意的是:如果HAR包會被打包成三方包使用,則HAR包中使用Worker僅支持通過相對路徑加載形式創(chuàng)建。
import { worker } from '@kit.ArkTS';
// @標識路徑加載形式:
// worker線程文件所在路徑: "har/src/main/ets/workers/worker.ets"
const workerStage4: worker.ThreadWorker = new worker.ThreadWorker('@har/ets/workers/worker.ets');
// 相對路徑加載形式:
// worker線程文件所在路徑: "har/src/main/ets/workers/worker.ets"
// 創(chuàng)建Worker對象的文件所在路徑:"har/src/main/ets/components/mainpage/MainPage.ets"
const workerStage5: worker.ThreadWorker = new worker.ThreadWorker('../../workers/worker.ets');
FA模型下的文件路徑規(guī)則
構(gòu)造函數(shù)中的scriptURL為:Worker線程文件與"{moduleName}/src/main/ets/MainAbility"的相對路徑。
import { worker } from '@kit.ArkTS';
// 主要說明以下三種場景:
// 場景1: Worker線程文件所在路徑:"{moduleName}/src/main/ets/MainAbility/workers/worker.ets"
const workerFA1: worker.ThreadWorker = new worker.ThreadWorker("workers/worker.ets", {name:"first worker in FA model"});
// 場景2: Worker線程文件所在路徑:"{moduleName}/src/main/ets/workers/worker.ets"
const workerFA2: worker.ThreadWorker = new worker.ThreadWorker("../workers/worker.ets");
// 場景3: Worker線程文件所在路徑:"{moduleName}/src/main/ets/MainAbility/ThreadFile/workers/worker.ets"
const workerFA3: worker.ThreadWorker = new worker.ThreadWorker("ThreadFile/workers/worker.ets");
HarmonyOS與OpenHarmony鴻蒙文檔籽料:mau123789是v直接拿
生命周期注意事項
- Worker的創(chuàng)建和銷毀耗費性能,建議開發(fā)者合理管理已創(chuàng)建的Worker并重復(fù)使用。Worker空閑時也會一直運行,因此當不需要Worker時,可以調(diào)用[terminate()]接口或[parentPort.close()]方法主動銷毀Worker。若Worker處于已銷毀或正在銷毀等非運行狀態(tài)時,調(diào)用其功能接口,會拋出相應(yīng)的錯誤。
- Worker的數(shù)量由內(nèi)存管理策略決定,設(shè)定的內(nèi)存閾值為1.5GB和設(shè)備物理內(nèi)存的60%中的較小者。在內(nèi)存允許的情況下,系統(tǒng)最多可以同時運行64個Worker。如果嘗試創(chuàng)建的Worker數(shù)量超出這一上限,系統(tǒng)將拋出錯誤:“Worker initialization failure, the number of workers exceeds the maximum.”。實際運行的Worker數(shù)量會根據(jù)當前內(nèi)存使用情況動態(tài)調(diào)整。一旦所有Worker和主線程的累積內(nèi)存占用超過了設(shè)定的閾值,系統(tǒng)將觸發(fā)內(nèi)存溢出(OOM)錯誤,導(dǎo)致應(yīng)用程序崩潰。
說明: FA模型每個Ability都有一個獨立的線程,Emiter可用于Ability線程內(nèi)、Ability線程間、Ability線程與Worker線程的事件同步。
審核編輯 黃宇
-
鴻蒙
+關(guān)注
關(guān)注
56文章
2267瀏覽量
42481
發(fā)布評論請先 登錄
相關(guān)推薦
評論