鴻蒙程式設計江湖:深入理解TaskPool和Worker的併發任務執行

SameX發表於2024-10-25

本文旨在深入探討華為鴻蒙HarmonyOS Next系統(截止目前API12)的技術細節,基於實際開發實踐進行總結。主要作為技術分享與交流載體,難免錯漏,歡迎各位同仁提出寶貴意見和問題,以便共同進步。本文為原創內容,任何形式的轉載必須註明出處及原作者。

鴻蒙系統提供了兩種併發能力:TaskPool 和 Worker。它們都基於 Actor 併發模型實現,但它們的使用場景和功能有所不同。

  • TaskPool:TaskPool 是一個多執行緒執行環境,它提供了任務的執行、取消、優先順序設定等功能。TaskPool 適用於獨立任務,例如計算密集型任務、I/O 密集型任務等。
  • Worker:Worker 是一個可以長時間執行的後臺執行緒,它支援與宿主執行緒之間的訊息傳遞。Worker 適用於長時間執行的任務,例如後臺資料處理、模型訓練等。

TaskPool 和 Worker 的區別與使用場景

特性 TaskPool Worker
記憶體模型 執行緒間隔離,記憶體不共享 執行緒間隔離,記憶體不共享
引數傳遞機制 採用標準的結構化克隆演算法(Structured Clone)進行序列化、反序列化,完成引數傳遞。支援 ArrayBuffer 轉移和 SharedArrayBuffer 共享。 採用標準的結構化克隆演算法(Structured Clone)進行序列化、反序列化,完成引數傳遞。支援 ArrayBuffer 轉移和 SharedArrayBuffer 共享。
引數傳遞 直接傳遞,無需封裝,預設進行 transfer。 訊息物件唯一引數,需要自己封裝。
方法呼叫 直接將方法傳入呼叫。 在 Worker 執行緒中進行訊息解析並呼叫對應方法。
返回值 非同步呼叫後預設返回。 主動傳送訊息,需在 onmessage 解析賦值。
生命週期 TaskPool 自動管理生命週期,無需關心任務負載高低。 開發者自行管理 Worker 的數量及生命週期。
任務池個數上限 自動管理,無需配置。 同個程序下,最多支援同時開啟 64 個 Worker 執行緒,實際數量由程序記憶體決定。
任務執行時長上限 3 分鐘(不包含 Promise 和 async/await 非同步呼叫的耗時,例如網路下載、檔案讀寫等 I/O 任務的耗時),長時任務無執行時長上限。 無限制。
設定任務的優先順序 支援配置任務優先順序。 不支援。
執行任務的取消 支援取消已經發起的任務。 不支援。
執行緒複用 支援。 不支援。
任務延時執行 支援。 不支援。
設定任務依賴關係 支援。 不支援。
序列佇列 支援。 不支援。
任務組 支援。 不支援。
使用場景
  • TaskPool:適用於獨立任務,例如計算密集型任務、I/O 密集型任務等。
  • Worker:適用於長時間執行的任務,例如後臺資料處理、模型訓練等。

TaskGroup 的管理與任務優先順序

TaskGroup:TaskGroup 是一個任務集合,可以將多個任務新增到 TaskGroup 中,並一起執行。TaskGroup 支援配置任務的優先順序。
示例

import { taskpool } from '@kit.ArkTS';
@Concurrent
function add(num1: number, num2: number): number {
  return num1 + num2;
}
@Concurrent
function subtract(num1: number, num2: number): number {
  return num1 - num2;
}
async function concurrentFunc() {
  const task1 = new taskpool.Task(add, 1, 2);
  const task2 = new taskpool.Task(subtract, 3, 4);
  const group = new taskpool.TaskGroup();
  group.addTask(task1);
  group.addTask(task2);
  group.addTask(task1); // 新增重複任務
  await taskpool.execute(group, taskpool.Priority.HIGH);
}

任務優先順序

  • Priority.IDLE:後臺任務,優先順序最低。
  • Priority.LOW:低優先順序任務。
  • Priority.MEDIUM:中等優先順序任務。
  • Priority.HIGH:高優先順序任務。

任務的新增與執行邏輯

任務新增

const task = new taskpool.Task(func, args);

任務執行

await taskpool.execute(task);

任務取消

taskpool.cancel(task);

示例程式碼:透過 TaskPool 執行 CPU 密集型任務的示例

以下是一個簡單的示例,演示如何使用 TaskPool 執行 CPU 密集型任務:

import { taskpool } from '@kit.ArkTS';
@Concurrent
function complexCalculation(data: ArrayBuffer): ArrayBuffer {
  // 執行復雜的計算操作
  return data;
}
async function concurrentCalculation() {
  const data = new ArrayBuffer(1024);
  const task = new taskpool.Task(complexCalculation, data);
  await taskpool.execute(task);
}
@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .onClick(async () => {
            await concurrentCalculation();
          })
          .width('100%');
      }
    }
    .height('100%');
  }
}

這段程式碼定義了一個名為 Index 的元件,並在元件中顯示了一條文字訊息 "Hello World"。點選按鈕會執行 concurrentCalculation 函式,該函式建立一個併發任務並執行它。任務完成後,會在控制檯輸出結果。

總結

透過以上介紹,您可以瞭解到鴻蒙系統中的 TaskPool 和 Worker 併發能力的使用方法。TaskPool 和 Worker 都是基於 Actor 併發模型實現的,但它們的使用場景和功能有所不同。希望本文能夠幫助您掌握鴻蒙系統中的併發程式設計技術,並開發出更優秀的鴻蒙應用。

相關文章