在 ArkTS 的并发体系中,Worker 的定位是“重量级后台线程”,而对于开发者关心的协程,ArkTS 有一套独特的实现逻辑。
1. Worker 的创建成本有多高?
由于 ArkTS 采用 Actor 内存隔离模型,创建一个 Worker 的成本显著高于传统 Java/C++ 线程:
- 独立的 ArkTS 引擎实例:每个 Worker 启动时,系统都会为其分配一个完全独立的虚拟机实例(ArkTS Runtime)。这意味着它有自己的指令执行器、堆栈空间和辅助线程。
- 内存开销(Memory Cost) :创建一个空的 Worker 大约会占用 2MB ~ 5MB 的物理内存。如果 Worker 中加载了复杂的业务代码或第三方库,这个数字会迅速上升。
- 时间开销(Time Cost) :Worker 的启动涉及二进制字节码的加载、运行环境初始化等。在高负载环境下,启动一个 Worker 可能需要 50ms ~ 100ms。
- 数量限制:系统目前限制单个应用进程同时运行的 Worker 数量(API 11 之后限制提升至 64 个,但建议保持在 8 个以内)。
结论: Worker 绝不适合“即用即建”。它应该用于长生命周期、常驻型的任务。对于短促的任务,请务必使用 TaskPool,它底层实现了线程池复用,创建成本几乎为零。
2. 是否支持协程调度器?
结论:ArkTS 并不提供像 Kotlin/Go 那样的原生“协程(Coroutine)”调度器,但它通过 async/await 实现了类似的异步非阻塞效果。
在 HarmonyOS 的架构中,开发者感知到的“异步”其实是由 微任务(Microtask) 驱动的:
A. 它是如何运作的?
当你调用一个 async 函数并 await 时:
- 当前函数会被挂起(Suspend) 。
- 线程不会阻塞,它会回到 Event Loop(事件循环) 去处理其他任务(如 UI 渲染)。
- 当异步操作完成后,结果会作为一个微任务加入队列,主线程在空闲时恢复执行该函数。
B. 为什么没有独立的“协程调度器”?
- 单线程事件循环:在 ArkTS 的主线程中,只有一个调度核心,即事件循环。它不需要像多线程协程那样在多个物理线程间切换上下文(Context Switch)。
- 任务分流机制:如果你需要真正的并行处理,ArkTS 引导你使用 TaskPool。TaskPool 底层有一个名为 FFRT(Function Flow Runtime) 的调度框架,它实际上扮演了“原生级协程调度器”的角色,自动管理着物理线程池,并将你提交的任务均匀分配到 CPU 核心。
3. Worker vs TaskPool 选型决策表
| 特性 | Worker | TaskPool (类似协程池) |
|---|---|---|
| 创建成本 | 极高 (独立虚拟机) | 极低 (线程池复用) |
| 通信方式 | 持续的双向消息流 (postMessage) | 基于结果的单次返回 (Promise) |
| 任务上限 | 受系统硬限制 (64个) | 无固定上限,系统自动调节 |
| 适用场景 | 长时运行(如 Socket、持续下载) | 短时并行(如 JSON 解析、图像计算) |
| 调度能力 | 开发者手动调度 | 系统级 FFRT 自动调度 (QoS) |
性能调优建议:
- 禁忌操作:严禁在
for循环中频繁new Worker()。 - TaskPool 优先:除非你需要跨越多个生命周期维持一个长连接,否则 90% 的并发场景应优先考虑 TaskPool。
- 协程陷阱:记住
async/await只是把任务排队,它并不能让主线程的同步计算变快。如果你的循环计算耗时,await也会卡死 UI。