6-7.【多线程】大量异步任务同时执行可能带来什么问题?如何控制并发数量?是否可以做任务合并?

0 阅读3分钟

在 ArkTS 的并发模型中,虽然 TaskPoolWorker 提供了强大的多线程能力,但“大量异步任务同时执行”并非没有代价。如果缺乏治理,应用会从“流畅”迅速转向“卡顿”甚至“崩溃”。


1. 大量异步任务同时执行可能带来的问题

  • 内存压力与 OOM (Out of Memory)

    每个异步任务在挂起或执行时都需要占用闭包内存、参数拷贝内存。如果是 TaskPool 任务,跨线程传递大数据会产生大量的序列化副本。任务过多会触发频繁的 GC,甚至直接导致应用被系统杀掉。

  • 线程池饱和与调度延迟

    TaskPool 的底层线程数是有限的(通常与 CPU 核心数相关)。当任务塞满队列,新发起的紧急 UI 任务(如点击反馈)必须排队,导致明显的交互延迟。

  • 主线程“回调淹没”

    虽然任务在后台跑,但所有任务完成后的 Promise.then()callback 都会回到主线程执行。如果一秒内有数千个任务同时返回,主线程会因为处理这些回调而无法执行渲染指令,造成掉帧。

  • 系统资源争抢 (CPU/IO)

    大量并发任务会争抢 CPU 时间片和磁盘 I/O 读写带宽,导致整体执行效率下降,设备发热严重。


2. 如何控制并发数量?

在 ArkTS 中,控制并发主要有三种手段:

A. 使用 Promise 队列(信号量机制)

这是最通用的做法。通过一个计数器限制同时处于 Pending 状态的 Promise 数量。

TypeScript

async function limitConcurrency(tasks: (() => Promise<any>)[], limit: number) {
  const results = [];
  const executing = [];
  for (const task of tasks) {
    const p = task().then(res => {
      executing.splice(executing.indexOf(p), 1);
      return res;
    });
    executing.push(p);
    results.push(p);
    if (executing.length >= limit) {
      await Promise.race(executing); // 达到上限,等待其中一个完成
    }
  }
  return Promise.all(results);
}

B. 利用 TaskPool 的任务组 (TaskGroup)

如果你有一批相关的任务,可以使用 taskpool.TaskGroup。虽然它本身不直接限制物理并发数,但你可以分批(Batching)将任务加入组中执行,从而人为控制节奏。

C. 串行执行器 (SequenceRunner)

对于必须按顺序且同一时间只能执行一个的任务,使用 taskpool.SequenceRunner。它会自动帮你排队,确保并发数始终为 1。


3. 是否可以做任务合并?

完全可以,且这是性能优化的“高阶招式”。

A. 数据侧合并 (Batching)

不要发 1000 个任务去数据库写 1000 条数据,而是发 1 个任务去写 1000 条数据的数组。

  • 收益:减少了 999 次跨线程通信的开销和线程上下文切换。

B. 请求侧合并 (Debounce / Throttle)

对于高频触发的任务(如搜索框输入、滑动时的实时计算):

  • 防抖 (Debounce) :用户停止输入 300ms 后再发任务。
  • 节流 (Throttle) :每隔 100ms 最多执行一次任务。

C. 结果侧合并 (Promise Memoization)

如果多个组件同时请求同一个耗时计算的结果,可以建立一个单例缓存。

  1. 第一个请求发起时,记录该 Promise
  2. 后续请求直接返回同一个 Promise 实例,而不是开启新任务。

总结:大型项目的并发治理清单

优化维度推荐手段
控制带宽限制最大并发数(如 3-5 个),防止资源耗尽。
减少通信任务尽量“大颗粒化”,合并零散的小任务。
区分优先级核心 UI 任务用 Priority.HIGH,预加载任务用 Priority.LOW
异步转同步顺序依赖明显的任务改用 await 链式调用。

架构师建议:

在 ArkUI 中,并发不是越多越好。**“恰到好处的并发”**是让 CPU 保持在 80% 左右的平稳负载,而不是瞬间飙升到 100% 后陷入长时间的排队阻塞。