本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

一、TaskPool 概念

  • TaskPool 是 ArkTS 提供的多线程环境,用于在应用程序中执行并发任务,旨在降低资源消耗、提升系统性能

  • 开发者无需管理线程生命周期,由系统统一管理线程的创建、调度和销毁。

二、运作机制

1. 基本流程

  1. 提交任务:宿主线程将任务提交到任务队列。

  2. 系统调度:系统根据负载情况选择合适的工作线程执行任务。

  3. 返回结果:任务执行完成后,将结果返回给宿主线程。

2. 线程管理特性

  • 默认启动一个工作线程,任务增多时自动扩容

  • 最大线程数由设备物理核数决定。

  • 空闲时自动缩容,减少线程数量以节省资源。

  • 支持任务优先级任务取消等控制。

三、使用注意事项

1. 函数装饰器要求

  • 任务函数必须使用 @Concurrent 装饰器标注,且只能在 .ets 文件中使用。

  • 从 API 11 开始,跨线程传递带方法的类必须使用 @Sendable 装饰器。

2. 执行时长限制

  • 任务在 TaskPool 中的同步执行时间不能超过 3 分钟(不包括异步等待时间)。

  • 可通过 Task 的 ioDurationcpuDuration 属性获取 I/O 和 CPU 耗时。

3. 参数与返回值类型

  • 任务函数的参数和返回值必须支持序列化

  • 不支持使用 @State@Prop@Link 等装饰的复杂类型。

4. ArrayBuffer 传输方式

  • 默认是转移(Transfer),可通过 setTransferList() 设置。

  • 如需多次使用同一 ArrayBuffer,应使用 setCloneList() 改为拷贝传递

5. 模块使用限制

  • TaskPool 工作线程只能使用线程安全的模块

  • 不支持 UI 操作、非线程安全模块、以及仅支持主线程的模块(如 ApplicationContext)。

  • 不支持在 TaskPool 中使用 AppStorage

6. 其他限制

  • 序列化数据量限制为 16MB

  • Promise 不支持跨线程传递,返回 pending 或 rejected 状态会失败。

  • 不支持指定运行线程,任务由系统分配至空闲线程。

  • IDLE 优先级任务仅在所有线程空闲时执行,且同一时间只执行一个。

四、@Concurrent 装饰器

1. 使用规范

项目 说明
装饰器参数
使用场景 仅 Stage 模型、.ets 文件
支持的函数类型 async 函数、普通函数(不支持 generator、箭头函数、类方法、匿名函数)
变量访问 允许:局部变量、入参、import 变量;禁止:闭包变量
返回值类型 必须支持序列化

2. 示例

1:基本并发函数
import { taskpool } from '@kit.ArkTS';

@Concurrent
function computeSum(a: number, b: number): number {
  return a + b;
}

async function runConcurrentTask(): Promise<void> {
  const task = new taskpool.Task(computeSum, 10, 20);
  const result = await taskpool.execute(task);
  console.info(`计算结果: ${result}`); // 输出:计算结果: 30
}
2:并发函数返回 Promise
@Concurrent
async function fetchData(id: number): Promise<string> {
  return await new Promise((resolve) => {
    setTimeout(() => {
      resolve(`Data for id: ${id}`);
    }, 500);
  });
}

async function runAsyncTask(): Promise<void> {
  const task = new taskpool.Task(fetchData, 1001);
  const data = await taskpool.execute(task);
  console.info(`获取数据: ${data}`);
}
3:使用外部定义的类和函数
// utils.ets
export function processValue(val: number): number {
  return val * 2;
}

@Sendable
export class DataProcessor {
  process(input: string): string {
    return `Processed: ${input}`;
  }
}

// main.ets
import { taskpool } from '@kit.ArkTS';
import { processValue, DataProcessor } from './utils';

@Concurrent
function runExternalLogic(): string {
  const value = processValue(5); // 正确:使用导入函数
  const processor = new DataProcessor(); // 正确:使用导入的 @Sendable 类
  return processor.process(`value is ${value}`);
}

五、TaskPool 扩缩容机制

1. 扩容条件

  • 当任务队列中有新任务提交,且当前空闲线程数小于待执行任务数时触发扩容。

  • 系统根据负载计算所需线程数并创建新工作线程。

2. 缩容条件

  • 每 30 秒检测一次负载。

  • 释放线程需满足:

    • 空闲时间 ≥ 30 秒;

    • 未执行 LongTask

    • 无未释放的句柄(如 Timer);

    • 非调试状态;

    • 无未销毁的子 Worker。

六、适用场景

  • 适用:短时任务、无状态任务、CPU 密集型计算、I/O 异步处理。

  • 不适用:长时任务(超过3分钟)、需指定线程、需操作 UI 的任务(推荐使用 Worker)。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐