TaskPool和Worker的對(duì)比

2024-02-16 13:44 更新

TaskPool(任務(wù)池)和Worker的作用是為應(yīng)用程序提供一個(gè)多線(xiàn)程的運(yùn)行環(huán)境,用于處理耗時(shí)的計(jì)算任務(wù)或其他密集型任務(wù)??梢杂行У乇苊膺@些任務(wù)阻塞主線(xiàn)程,從而最大化系統(tǒng)的利用率,降低整體資源消耗,并提高系統(tǒng)的整體性能。

本文將從實(shí)現(xiàn)特點(diǎn)適用場(chǎng)景兩個(gè)方面來(lái)進(jìn)行TaskPool與Worker的比較,同時(shí)提供了各自運(yùn)作機(jī)制和注意事項(xiàng)的相關(guān)說(shuō)明。

實(shí)現(xiàn)特點(diǎn)對(duì)比

表1 TaskPool和Worker的實(shí)現(xiàn)特點(diǎn)對(duì)比

實(shí)現(xiàn)

TaskPool

Worker

內(nèi)存模型

線(xiàn)程間隔離,內(nèi)存不共享。

線(xiàn)程間隔離,內(nèi)存不共享。

參數(shù)傳遞機(jī)制

采用標(biāo)準(zhǔn)的結(jié)構(gòu)化克隆算法(Structured Clone)進(jìn)行序列化、反序列化,完成參數(shù)傳遞。

支持ArrayBuffer轉(zhuǎn)移和SharedArrayBuffer共享。

采用標(biāo)準(zhǔn)的結(jié)構(gòu)化克隆算法(Structured Clone)進(jìn)行序列化、反序列化,完成參數(shù)傳遞。

支持ArrayBuffer轉(zhuǎn)移和SharedArrayBuffer共享。

參數(shù)傳遞

直接傳遞,無(wú)需封裝,默認(rèn)進(jìn)行transfer。

消息對(duì)象唯一參數(shù),需要自己封裝。

方法調(diào)用

直接將方法傳入調(diào)用。

在Worker線(xiàn)程中進(jìn)行消息解析并調(diào)用對(duì)應(yīng)方法。

返回值

異步調(diào)用后默認(rèn)返回。

主動(dòng)發(fā)送消息,需在onmessage解析賦值。

生命周期

TaskPool自行管理生命周期,無(wú)需關(guān)心任務(wù)負(fù)載高低。

開(kāi)發(fā)者自行管理Worker的數(shù)量及生命周期。

任務(wù)池個(gè)數(shù)上限

自動(dòng)管理,無(wú)需配置。

同個(gè)進(jìn)程下,最多支持同時(shí)開(kāi)啟8個(gè)Worker線(xiàn)程。

任務(wù)執(zhí)行時(shí)長(zhǎng)上限

無(wú)限制。

無(wú)限制。

設(shè)置任務(wù)的優(yōu)先級(jí)

不支持。

不支持。

執(zhí)行任務(wù)的取消

支持取消任務(wù)隊(duì)列中等待的任務(wù)。

不支持。

適用場(chǎng)景對(duì)比

TaskPool偏向獨(dú)立任務(wù)維度,該任務(wù)在線(xiàn)程中執(zhí)行,無(wú)需關(guān)注線(xiàn)程的生命周期,超長(zhǎng)任務(wù)(大于3分鐘)會(huì)被系統(tǒng)自動(dòng)回收;而Worker偏向線(xiàn)程的維度,支持長(zhǎng)時(shí)間占據(jù)線(xiàn)程執(zhí)行,需要主動(dòng)管理線(xiàn)程生命周期。

常見(jiàn)的一些開(kāi)發(fā)場(chǎng)景及適用具體說(shuō)明如下:

  • 有關(guān)聯(lián)的一系列同步任務(wù)。例如在一些需要?jiǎng)?chuàng)建、使用句柄的場(chǎng)景中,句柄創(chuàng)建每次都是不同的,該句柄需永久保存,保證使用該句柄進(jìn)行操作,需要使用Worker。
  • 需要頻繁取消的任務(wù)。例如圖庫(kù)大圖瀏覽場(chǎng)景,為提升體驗(yàn),會(huì)同時(shí)緩存當(dāng)前圖片左右側(cè)各2張圖片,往一側(cè)滑動(dòng)跳到下一張圖片時(shí),要取消另一側(cè)的一個(gè)緩存任務(wù),需要使用TaskPool。
  • 大量或者調(diào)度點(diǎn)較分散的任務(wù)。例如大型應(yīng)用的多個(gè)模塊包含多個(gè)耗時(shí)任務(wù),不方便使用8個(gè)Worker去做負(fù)載管理,推薦采用TaskPool。

TaskPool運(yùn)作機(jī)制

圖1 TaskPool運(yùn)作機(jī)制示意圖

TaskPool支持開(kāi)發(fā)者在主線(xiàn)程封裝任務(wù)拋給任務(wù)隊(duì)列,系統(tǒng)選擇合適的工作線(xiàn)程,進(jìn)行任務(wù)的分發(fā)及執(zhí)行,再將結(jié)果返回給主線(xiàn)程。接口直觀(guān)易用,支持任務(wù)的執(zhí)行、取消。工作線(xiàn)程數(shù)量上限為4。

Worker運(yùn)作機(jī)制

圖2 Worker運(yùn)作機(jī)制示意圖

創(chuàng)建Worker的線(xiàn)程稱(chēng)為宿主線(xiàn)程(不一定是主線(xiàn)程,工作線(xiàn)程也支持創(chuàng)建Worker子線(xiàn)程),Worker自身的線(xiàn)程稱(chēng)為Worker子線(xiàn)程(或Actor線(xiàn)程、工作線(xiàn)程)。每個(gè)Worker子線(xiàn)程與宿主線(xiàn)程擁有獨(dú)立的實(shí)例,包含基礎(chǔ)設(shè)施、對(duì)象、代碼段等。Worker子線(xiàn)程和宿主線(xiàn)程之間的通信是基于消息傳遞的,Worker通過(guò)序列化機(jī)制與宿主線(xiàn)程之間相互通信,完成命令及數(shù)據(jù)交互。

TaskPool注意事項(xiàng)

  • 實(shí)現(xiàn)任務(wù)的函數(shù)需要使用裝飾器@Concurrent標(biāo)注,且僅支持在.ets文件中使用。

  • 實(shí)現(xiàn)任務(wù)的函數(shù)入?yún)⑿铦M(mǎn)足序列化支持的類(lèi)型,詳情請(qǐng)參見(jiàn)數(shù)據(jù)傳輸對(duì)象。

  • 由于不同線(xiàn)程中上下文對(duì)象是不同的,因此TaskPool工作線(xiàn)程只能使用線(xiàn)程安全的庫(kù),例如UI相關(guān)的非線(xiàn)程安全庫(kù)不能使用。

  • 序列化傳輸?shù)臄?shù)據(jù)量大小限制為16MB。

Worker注意事項(xiàng)

  • 創(chuàng)建Worker時(shí),傳入的Worker.ts路徑在不同版本有不同的規(guī)則,詳情請(qǐng)參見(jiàn)文件路徑注意事項(xiàng)

  • Worker創(chuàng)建后需要手動(dòng)管理生命周期,且最多同時(shí)運(yùn)行的Worker子線(xiàn)程數(shù)量為8個(gè),詳情請(qǐng)參見(jiàn)生命周期注意事項(xiàng)

  • Ability類(lèi)型的Module支持使用Worker,Library類(lèi)型的Module不支持使用Worker。

  • 創(chuàng)建Worker不支持使用其他Module的Worker.ts文件,即不支持跨模塊調(diào)用Worker。

  • 由于不同線(xiàn)程中上下文對(duì)象是不同的,因此Worker線(xiàn)程只能使用線(xiàn)程安全的庫(kù),例如UI相關(guān)的非線(xiàn)程安全庫(kù)不能使用。

  • 序列化傳輸?shù)臄?shù)據(jù)量大小限制為16MB。

文件路徑注意事項(xiàng)

當(dāng)使用Worker模塊具體功能時(shí),均需先構(gòu)造Worker實(shí)例對(duì)象,其構(gòu)造函數(shù)與API版本相關(guān)。

  1. // 導(dǎo)入模塊
  2. import worker from '@ohos.worker';
  3. // API 9及之后版本使用:
  4. const worker1 = new worker.ThreadWorker(scriptURL);
  5. // API 8及之前版本使用:
  6. const worker1 = new worker.Worker(scriptURL);

構(gòu)造函數(shù)需要傳入Worker的路徑(scriptURL),Worker文件存放位置默認(rèn)路徑為Worker文件所在目錄與pages目錄屬于同級(jí)。

Stage模型

構(gòu)造函數(shù)中的scriptURL示例如下:

  1. // 導(dǎo)入模塊
  2. import worker from '@ohos.worker';
  3. // 寫(xiě)法一
  4. // Stage模型-目錄同級(jí)(entry模塊下,workers目錄與pages目錄同級(jí))
  5. const worker1 = new worker.ThreadWorker('entry/ets/workers/MyWorker.ts', {name:"first worker in Stage model"});
  6. // Stage模型-目錄不同級(jí)(entry模塊下,workers目錄是pages目錄的子目錄)
  7. const worker2 = new worker.ThreadWorker('entry/ets/pages/workers/MyWorker.ts');
  8. // 寫(xiě)法二
  9. // Stage模型-目錄同級(jí)(entry模塊下,workers目錄與pages目錄同級(jí)),假設(shè)bundlename是com.example.workerdemo
  10. const worker3 = new worker.ThreadWorker('@bundle:com.example.workerdemo/entry/ets/workers/worker');
  11. // Stage模型-目錄不同級(jí)(entry模塊下,workers目錄是pages目錄的子目錄),假設(shè)bundlename是com.example.workerdemo
  12. const worker4 = new worker.ThreadWorker('@bundle:com.example.workerdemo/entry/ets/pages/workers/worker');
  • 基于Stage模型工程目錄結(jié)構(gòu),寫(xiě)法一的路徑含義:

    • entry:module.json5文件中module的name屬性對(duì)應(yīng)值。
    • ets:用于存放ets源碼,固定目錄。
    • workers/MyWorker.ts:worker源文件在ets目錄下的路徑。
  • 基于Stage模型工程目錄結(jié)構(gòu),寫(xiě)法二的路徑含義:

    • @bundle:固定標(biāo)簽。
    • bundlename:當(dāng)前應(yīng)用包名。
    • entryname:module.json5文件中module的name屬性對(duì)應(yīng)值。
    • ets:用于存放ets源碼,固定目錄。
    • workerdir/workerfile:worker源文件在ets目錄下的路徑,可不帶文件后綴名。

FA模型

構(gòu)造函數(shù)中的scriptURL示例如下:

  1. // 導(dǎo)入模塊
  2. import worker from '@ohos.worker';
  3. // FA模型-目錄同級(jí)(entry模塊下,workers目錄與pages目錄同級(jí))
  4. const worker1 = new worker.ThreadWorker('workers/worker.js', {name:'first worker in FA model'});
  5. // FA模型-目錄不同級(jí)(entry模塊下,workers目錄與pages目錄的父目錄同級(jí))
  6. const worker2 = new worker.ThreadWorker('../workers/worker.js');

生命周期注意事項(xiàng)

  • Worker的創(chuàng)建和銷(xiāo)毀耗費(fèi)性能,建議開(kāi)發(fā)者合理管理已創(chuàng)建的Worker并重復(fù)使用。Worker空閑時(shí)也會(huì)一直運(yùn)行,因此當(dāng)不需要Worker時(shí),可以調(diào)用terminate()接口或parentPort.close()方法主動(dòng)銷(xiāo)毀Worker。若Worker處于已銷(xiāo)毀或正在銷(xiāo)毀等非運(yùn)行狀態(tài)時(shí),調(diào)用其功能接口,會(huì)拋出相應(yīng)的錯(cuò)誤。

  • Worker存在數(shù)量限制,支持最多同時(shí)存在8個(gè)Worker。

    • 在API version 8及之前的版本,當(dāng)Worker數(shù)量超出限制時(shí),會(huì)拋出“Too many workers, the number of workers exceeds the maximum.”錯(cuò)誤。
    • 從API version 9開(kāi)始,當(dāng)Worker數(shù)量超出限制時(shí),會(huì)拋出“Worker initialization failure, the number of workers exceeds the maximum.”錯(cuò)誤。
以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)