Skip to content

Dart Future / Event Loop / Isolate

Dart 的并发核心不是“线程池 + 回调地狱”,而是 单线程事件循环 + microtask queue + event queue + isolate 消息隔离

代码索引

主题Lab 说明源码
event loop / microtask / event queue / isolatedart-event-loop-isolateevent_loop_isolate_demo.dart

为什么需要

Flutter / Dart 面试和实际业务里,这些问题几乎必问:

  • 为什么 Future 不是线程?
  • Future.microtaskFuture(() {}) 到底差在哪?
  • await 后面的代码什么时候恢复?
  • CPU 密集任务为什么会卡 UI?
  • 什么时候必须上 isolate?

如果只会“Future 就是异步”,遇到卡顿、执行顺序、主线程阻塞问题会很难说清。

底层机制

1. 默认执行模型:单线程事件循环

Dart 默认在一个 isolate 内运行,核心调度模型是:

  • 同步代码先跑完
  • 再清空 microtask queue
  • 再从 event queue 取任务执行

所以常见优先级大致是:

text
sync code
> microtask
> event queue future / timer / IO completion

2. Future 不是线程

像下面这种:

dart
Future(() {
  // ...
});

默认只是把任务丢进当前 isolate 的 event queue,不是新线程。

3. microtask 会更早执行

例如:

dart
scheduleMicrotask(() => print('microtask'));
Future(() => print('event'));

通常会先看到:

text
microtask
event

因为 microtask queue 会在进入下一轮 event queue 前优先清空。

4. isolate 才是真正的并发隔离单元

isolate 特点:

  • 独立内存
  • 不共享对象
  • 靠消息传递
  • 更适合 CPU 密集任务

这也是 Flutter 中为什么:

  • 网络请求异步通常不需要 isolate
  • 但大 JSON 解析、图片处理、复杂计算有时要 isolate

Android / Flutter / Web / Backend 对照

维度DartFlutterJS / Web后台 Java/Kotlin
默认异步模型单 isolate 事件循环UI isolate 事件循环event loop线程池 / 协程 / 事件循环按框架而定
更高优先级队列microtaskmicrotaskmicrotask / promise job无直接等价统一模型
普通异步队列event queueevent queuemacrotaskexecutor / dispatcher
真正并发隔离单元isolateisolate / computeWeb WorkerThread / process

常见场景

1. 页面启动时多个 Future 排序不符合预期

如果你同时用了:

  • scheduleMicrotask
  • Future.microtask
  • Future(() {})

执行顺序常常和直觉不一样。

对应 Labdart-event-loop-isolate · event_loop_isolate_demo.dart

2. Flutter UI 卡顿

如果 CPU 密集计算放在主 isolate:

  • Future 语法看起来是异步
  • 但本质仍可能阻塞当前 isolate 的执行

这时要考虑:

  • Isolate.run
  • compute

3. 大量 JSON / 加解密 / 数据清洗

这类任务更适合 isolate,而不是只靠普通 Future 包一层。

常见坑

现象修法
Future 当线程以为不会卡 UI先分清是否仍在当前 isolate
滥用 microtask某些回调顺序异常、可读性差只在必须抢优先级时使用
所有异步任务都上 isolate复杂度高、消息传递成本增加只给 CPU 密集任务上 isolate
认为 await 会立即切线程回来顺序理解错误理解它只是等待 future 完成后恢复 continuation

与相近概念对比

概念本质适合场景
Future(() {})event queue 任务普通异步调度
Future.microtaskmicrotask queue 任务需要更高优先级的短逻辑
awaitcontinuation 恢复点顺序化异步代码
Isolate.run独立 isolateCPU 密集任务

对应实验

各章节内已嵌入跳转链接;此处汇总全部 Lab:

Lab说明源码
dart-event-loop-isolatedart-event-loop-isolateevent_loop_isolate_demo.dart

复习检查题

  1. 为什么说 Future 不是线程?

    :因为普通 Future 默认仍在当前 isolate 的事件循环中调度,只是把代码延后执行;它不会自动创建独立线程/独立内存执行单元。

  2. Future.microtask 为什么通常先于 Future(() {}) 执行?

    :因为 microtask queue 会在进入下一轮 event queue 前优先清空,所以 microtask 的优先级更高。

  3. 什么场景下应优先考虑 isolate?

    :CPU 密集任务,例如大 JSON 解析、复杂计算、图片处理、加解密等;纯 IO 异步通常不需要 isolate。

速记

  • 同步先跑完
  • microtask 先于 event queue
  • Future 不是线程
  • isolate 才是独立并发单元
  • UI 卡顿先怀疑主 isolate 被 CPU 任务占住