Dart 事件循環(huán)與異步任務(wù)執(zhí)行順序全解析(Event Loop, Microtask Queue, Future, Timer, Event Queue, Stream)

Dart 作為單線程異步編程模型的代表語言,其核心運行機制EventLoop(事件循環(huán))是理解異步代碼執(zhí)行順序的關(guān)鍵。本文將系統(tǒng)梳理 EventLoop 原理、核心名詞定義,并通過基礎(chǔ)題、進階題、綜合地獄題三層實戰(zhàn)案例,徹底講透 microtask、Futureasync/await、Timer 的執(zhí)行規(guī)律。

一、核心概念:EventLoop 與關(guān)鍵名詞解析

1. Dart 運行基礎(chǔ)

Dart 是單線程模型,不存在多線程并發(fā)競爭問題,所有異步任務(wù)都依靠事件循環(huán)(EventLoop)調(diào)度執(zhí)行。
一個 Dart 線程中,EventLoop 管理兩個任務(wù)隊列,任務(wù)執(zhí)行有嚴(yán)格的優(yōu)先級規(guī)則。

2. 核心名詞與隊列

名詞 含義 包含任務(wù) 優(yōu)先級
同步代碼 主線程立即執(zhí)行的代碼(main函數(shù)內(nèi)同步邏輯) 普通print、函數(shù)同步調(diào)用 最高
Microtask Queue(微任務(wù)隊列) 內(nèi)部高優(yōu)先級隊列,用于快速執(zhí)行輕量異步任務(wù) scheduleMicrotask()
Future.microtask()
Future.then()/.catchError()
await 后續(xù)代碼
次之
Event Queue(事件隊列) 外部事件隊列,處理耗時/外部任務(wù) 普通Future()
Timer.run()/Future.delay()
IO/網(wǎng)絡(luò)/點擊事件
最低
Isolate Dart 獨立工作線程 擁有獨立的 EventLoop 和隊列,不共享內(nèi)存 與主線程隔離

3. EventLoop 執(zhí)行黃金定律

  1. 優(yōu)先執(zhí)行完所有同步代碼,同步代碼執(zhí)行期間,異步任務(wù)僅入隊,不執(zhí)行;
  2. 同步代碼結(jié)束 → 一次性清空整個微任務(wù)隊列
  3. 微任務(wù)隊列為空 → 從事件隊列取出 1 個任務(wù)執(zhí)行;
  4. 執(zhí)行完 1 個事件任務(wù) → 再次清空微任務(wù)隊列
  5. 循環(huán)往復(fù),直到所有隊列清空。

一句話總結(jié)同步代碼 > 微任務(wù)(Microtask) > 事件任務(wù)(Event/Future/Timer/Stream)

4. 比較特殊的幾個case

  1. async中的同步部分,是直接執(zhí)行的
  2. await后的代碼,整體是作為microtask,插入的方式

二、基礎(chǔ)實戰(zhàn)案例(入門必考)

Case 1:基礎(chǔ)任務(wù)調(diào)度

題目

void main() {
  print('A');

  Future(() => print('B'));
  Future.microtask(() => print('C'));
  scheduleMicrotask(() => print('D'));

  print('E');
}

執(zhí)行解析

  1. 執(zhí)行同步代碼:打印 A → 普通Future入Event隊列 → 兩個微任務(wù)入Microtask隊列 → 打印 E;
  2. 同步完成,清空微任務(wù)隊列:打印 C、D;
  3. 執(zhí)行Event隊列唯一任務(wù):打印 B。

輸出結(jié)果

A
E
C
D
B

Case 2:Future.then 坑點解析

題目

void main() {
  print('1');

  Future(() => print('2')).then((_) => print('3'));
  Future.microtask(() => print('4'));
  scheduleMicrotask(() => print('5'));

  print('6');
}

執(zhí)行解析

  1. 同步代碼:打印1 → Future入Event隊列 → 兩個微任務(wù)入隊 → 打印6;
  2. 清空微任務(wù):打印4、5;
  3. 執(zhí)行Event任務(wù)打印2;
  4. Future.then 屬于微任務(wù),立即執(zhí)行:打印3。

輸出結(jié)果

1
6
4
5
2
3

Case 3:microtask 的 then 案例

題目

void main() {
  print('1');

  Future.microtask(() => print('2')).then((_) => print('3'));
  scheduleMicrotask(() => print('4'));

  print('5');
}

執(zhí)行解析

  1. 同步代碼:打印1 → microtask入隊 → then等待 → 另一個microtask入隊 → 打印5;
  2. 清空微任務(wù)隊列:
    先執(zhí)行 microtask(2) → 觸發(fā) then(3)(加入微任務(wù)并立即執(zhí)行);
    再執(zhí)行 scheduleMicrotask(4)
  3. 全部微任務(wù)清空,無事件任務(wù)。

輸出結(jié)果

1
5
2
3
4

三、中高階實戰(zhàn)案例(混合 Timer + async/await)

Case 1:Timer + 鏈?zhǔn)?then 綜合題

題目

import 'dart:async';

void main() {
  print('A');

  Future(() => print('B')).then((_) => print('C'));
  Future.microtask(() => print('D'));
  Timer.run(() => print('E'));
  scheduleMicrotask(() => print('F'));
  Future(() => print('G'));

  print('H');
}

執(zhí)行解析

  1. 同步代碼:打印 A、H;
  2. 清空微任務(wù):打印 D、F;
  3. 執(zhí)行第一個Event任務(wù)(打印B),then觸發(fā)微任務(wù)打印C;
  4. 依次執(zhí)行剩余Event任務(wù):打印E、G。

輸出結(jié)果

A
H
D
F
B
C
E
G

Case 2:async/await 核心邏輯題

題目

import 'dart:async';

void main() {
  print('1');
  Future(() => print('2'));
  a();
  Future.microtask(() => print('3'));
  Timer.run(() => print('4'));
  print('5');
}

Future<void> a() async {
  print('6');
  await Future(() => print('7'));
  print('8');
}

執(zhí)行解析

void main() {
  print('1'); // 1
  Future(() => print('2')); // event queue 1
  a();
  Future.microtask(() => print('3')); // microtask queue 1
  Timer.run(() => print('4')); // event queue 3
  print('5'); // 3
}

Future<void> a() async {
  print('6'); // 2
  await Future(() => print('7')); // event queue 2
  print('8'); // event queue 2的同步代碼
}
  1. async函數(shù)同步部分立即執(zhí)行:打印6;
  2. await后的Future入Event隊列,后續(xù)代碼包裝為微任務(wù);
  3. 同步完成:打印1、6、5;
  4. 清空微任務(wù):打印3;
  5. 依次執(zhí)行Event隊列:打印2、7;
  6. 喚醒await微任務(wù):打印8;
  7. 執(zhí)行最后一個Event任務(wù):打印4。

輸出結(jié)果

1
6
5
3
2
7
8
4

四、究極地獄題(全覆蓋考點)

本題包含:Future、鏈?zhǔn)?code>then、microtaskTimer、async/await、嵌套微任務(wù),是 Flutter 中高級面試必考題。

題目

import 'dart:async';

void main() {
  print('1');

  Future(() => print('2'))
      .then((_) => print('3'))
      .then((_) => print('4'));

  Timer.run(() => print('5'));
  Future.microtask(() => print('6'));
  scheduleMicrotask(() => print('7'));

  foo();
  print('8');
}

Future<void> foo() async {
  print('9');
  await Future(() => print('10'));
  print('11');
  await Future.microtask(() => print('12'));
  print('13');
}

完整執(zhí)行流程(修正版,匹配真實運行結(jié)果)

  1. 同步代碼執(zhí)行:按順序打印 1 → 調(diào)用foo()同步打印9 → 回到main打印8;
  2. 同步代碼執(zhí)行完畢,清空Microtask隊列:依次打印6、7;
  3. EventLoop 取出 EventQueue 第一個任務(wù):執(zhí)行Future(2)打印2,鏈?zhǔn)?code>then作為微任務(wù)依次執(zhí)行,打印34;
  4. EventLoop 取出 EventQueue 第二個任務(wù):執(zhí)行Timer(5)打印5;
  5. EventLoop 取出 EventQueue 第三個任務(wù):執(zhí)行Future(10)打印10;
  6. await 后續(xù)代碼作為微任務(wù)執(zhí)行:打印11
  7. 執(zhí)行Future.microtask(12):打印12,隨后執(zhí)行剩余微任務(wù)打印13
  8. 所有隊列清空,流程結(jié)束。

最終輸出(真實執(zhí)行結(jié)果)

1
9
8
6
7
2
3
4
5
10
11
12
13

五、補充:Isolate 核心規(guī)則

  1. Isolate 是 Dart 的獨立線程,擁有自己的 EventLoop、微任務(wù)隊列、事件隊列;
  2. 不共享內(nèi)存、不共享隊列,主Isolate的任務(wù)執(zhí)行順序完全不受其他Isolate影響;
  3. 面試順序題中:Isolate內(nèi)部的print不參與主線程任務(wù)排序。

我直接幫你完美補充 Stream 在 EventLoop 里的執(zhí)行順序

完全貼合你這篇文章的風(fēng)格、格式、定律,無縫插入,你直接復(fù)制進文章即可。

我會講得超級清晰、不繞彎、面試直接用。


【補充】Stream 在 EventLoop 中的執(zhí)行規(guī)則(最重要 4 條)

Stream 屬于 Event Queue 事件任務(wù),和普通 Future()、Timer 同一個優(yōu)先級。

1. Stream 核心定位(直接進你的表格)

名詞 含義 優(yōu)先級
Stream 異步事件流(多次發(fā)射數(shù)據(jù)) 同 Event Queue,低于微任務(wù)

2. Stream 終極執(zhí)行定律(背這 4 條就夠)

  1. Stream.listen(...) 注冊是同步的
  2. Stream 發(fā)射數(shù)據(jù)(add、emit)是 Event Queue 事件任務(wù)
  3. Stream 的 listen 回調(diào) = Event 任務(wù)
  4. 執(zhí)行順序:同步 > Microtask > Stream = Future = Timer

3. 最關(guān)鍵結(jié)論(一句話)

Stream ≈ 可以多次觸發(fā)的 Future,全部走 Event Queue,優(yōu)先級和 Future 一模一樣,永遠(yuǎn)低于微任務(wù)。


4. 基礎(chǔ)案例:Stream vs Future vs Microtask(必看)

import 'dart:async';

void main() {
  print('A'); // 同步 1

  // Stream 走 Event Queue
  Stream.value('B').listen((val) => print(val));

  // Future 走 Event Queue
  Future(() => print('C'));

  // Microtask
  Future.microtask(() => print('D'));

  print('E'); // 同步 2
}

執(zhí)行順序

  1. 同步:A → E
  2. 微任務(wù):D
  3. Event 隊列(按加入順序):B → C

輸出

A
E
D
B
C

5. 進階:StreamController.add 執(zhí)行規(guī)則(面試最愛考)

import 'dart:async';

void main() {
  print('1');

  final sc = StreamController<int>();

  sc.stream.listen((val) {
    print('listen: $val'); // ?? Event 任務(wù)
  });

  print('2');

  sc.add(100); // ?? 發(fā)射事件 → 入 Event Queue

  Future.microtask(() => print('micro')); // ?? 微任務(wù)

  print('3');
}

執(zhí)行順序

  1. 同步:1 → 2 → 3
  2. 微任務(wù):micro
  3. Event:listen: 100

輸出

1
2
3
micro
listen: 100

6. 地獄題級別:Stream + async/await + Future + Microtask(你文章風(fēng)格)

import 'dart:async';

void main() {
  print('A');

  Stream.value('X').listen((val) => print(val)); // Event

  Future(() => print('B')); // Event
  Future.microtask(() => print('C')); // Micro

  foo();

  print('D');
}

Future<void> foo() async {
  print('E');
  await Future.microtask(() => print('F'));
  print('G');
}

輸出

A
E
D
C
F
G
X
B

7. 直接插入你文章「萬能記憶口訣」的最終版

我?guī)湍阊a成終極完整版口訣

  1. 同步優(yōu)先,全部跑完再處理異步;
  2. 微任務(wù)優(yōu)先級 > 事件任務(wù);
  3. 微任務(wù)一次性清空,事件任務(wù)一次執(zhí)行一個;
  4. Future本體是Event,then/await后續(xù)是Microtask;
  5. Stream 發(fā)射/監(jiān)聽 = Event,和 Future 同級;
  6. 執(zhí)行完一個Event,必清空一次Microtask;
  7. Timer 等同于普通Event任務(wù);
  8. Isolate 獨立隔離,不干擾主線程順序。

我?guī)湍憧偨Y(jié)成一句最精煉的(面試口述)

Stream 是異步事件流,所有發(fā)射和回調(diào)都走 Event Queue,執(zhí)行優(yōu)先級和 Future、Timer 完全一樣,永遠(yuǎn)低于微任務(wù)。listen 注冊是同步的,數(shù)據(jù)回調(diào)是異步的。


如果你愿意,我可以把 Stream 直接完美融入你整篇文章的結(jié)構(gòu)里,變成一篇完整、可直接發(fā)表、面試滿分的 Dart EventLoop 終極文章

六、萬能記憶口訣(通殺所有順序題)

  1. 同步優(yōu)先,全部跑完再處理異步;
  2. 微任務(wù)優(yōu)先級 > 事件任務(wù);
  3. 微任務(wù)一次性清空,事件任務(wù)一次執(zhí)行一個;
  4. Future本體是Event,then/await后續(xù)是Microtask;
  5. 執(zhí)行完一個Event,必清空一次Microtask;
  6. Timer 等同于普通Event任務(wù);
  7. Isolate 獨立隔離,不干擾主線程順序。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容