Dart
是基于 事件循環(huán)機(jī)制的單線程模型, 所以Dart
中沒有多線程, 也就沒有主線程與子線程之分。
- 單線程模型:一條執(zhí)行線上同時(shí)只能執(zhí)行一個(gè)任務(wù)炊甲,如果有耗時(shí)任務(wù)則需要放入隊(duì)列異步執(zhí)行卿啡。
- 多線程:充分利用處理器的多核優(yōu)勢(shì)進(jìn)行并行計(jì)算。
一颈娜、事件循環(huán)機(jī)制
對(duì)于用戶點(diǎn)擊, 滑動(dòng), 硬盤IO
訪問等事件, 你不知道何時(shí)發(fā)生或以什么順序發(fā)生, 所以得有一個(gè)永不停歇且不能阻塞的循環(huán)來等待處理這些 "突發(fā)" 事件. 于是, 基于 事件循環(huán)機(jī)制 的 單線程模型 就出現(xiàn)了。
Dart
的事件循環(huán)機(jī)制由一個(gè)消息循環(huán)(Event Looper
)和兩個(gè)消息隊(duì)列構(gòu)成蛹磺。兩個(gè)消息隊(duì)列分別是事件隊(duì)列(Event Queue
)和微任務(wù)隊(duì)列(Microtask Queue
)同仆。
1.Event Looper
Dart
在執(zhí)行完main
函數(shù)后, Event Looper
就開始工作, Event Looper
優(yōu)先全部執(zhí)行完 Microtask Queue
中的event
, 直到Microtask Queue
為空時(shí), 才會(huì)執(zhí)行Event Looper
中的 event
, Event Looper
為空時(shí)才可以退出循環(huán)俗批。
2.Event Queue
-
Event Queue
的 event 來源于外部事件或Future
。 - 外部事件:例如輸入/輸出, 手勢(shì), 繪制, 計(jì)時(shí)器,
Stream
等蕴侣, -
Future
:用于自定義Event Queue
事件臭觉。
對(duì)于外部事件, 一旦沒有任何 microtask 要執(zhí)行, Event loop 才會(huì)考慮 event queue 中的第一項(xiàng), 并且將會(huì)執(zhí)行它。
- 案例:向Event Queue中添加事件任務(wù)
Future(() {
// 事件任務(wù)
});
3.Microtask Queue
-
Microtask Queue
的優(yōu)先級(jí)高于Event Queue
. - 使用場(chǎng)景: 想要在稍后完成一些任務(wù)(microtask) 但又希望在執(zhí)行下一個(gè)事件(event)之前執(zhí)行.
Microtask 一般用于非常短的內(nèi)部異步動(dòng)作, 并且任務(wù)量非常少, 如果微任務(wù)非常多, 就會(huì)造成 Event Queue 排不上隊(duì), 會(huì)阻塞 Event Queue 的執(zhí)行(如: 用戶點(diǎn)擊沒有反應(yīng)). 所以, 大多數(shù)情況下優(yōu)先考慮使用 Event Queue, 整個(gè) Flutter 源代碼僅引用 scheduleMicroTask() 方法 7 次.
- 案例:向 Microtask Queue 添加微任務(wù):
scheduleMicrotask(() {
// 微任務(wù)
});
二狞膘、Future
1. Future 實(shí)例有 3 個(gè)常用方法:
- then((value){...}): 正常運(yùn)行時(shí)執(zhí)行
- catchError((err){...}): 出現(xiàn)錯(cuò)誤時(shí)執(zhí)行
- whenComplete((){...}): 不管成功與否都會(huì)執(zhí)行
2.鏈?zhǔn)秸{(diào)用
Future 可以在 then()方法中返回另一個(gè) Future 實(shí)例, 從而達(dá)到鏈?zhǔn)秸{(diào)用的效果, 這對(duì)那些有數(shù)據(jù)關(guān)聯(lián)的網(wǎng)絡(luò)請(qǐng)求很有用
3.其他
Future 除了默認(rèn)構(gòu)造器外, 還提供了幾個(gè)常用的命名構(gòu)造器:
- Future.value(): 創(chuàng)建一個(gè)返回具體數(shù)據(jù)的 Future 實(shí)例
- Future.error(): 創(chuàng)建一個(gè)返回錯(cuò)誤的 Future 實(shí)例
- Future.delayed(): 創(chuàng)建一個(gè)延時(shí)執(zhí)行的 Future 實(shí)例
三什乙、async/await
1、基本使用
- await 必須在 async 函數(shù)中使用
- async 函數(shù)返回的結(jié)果必須是一個(gè) Future
四辅愿、isolate
所有的 Dart 代碼都是在 isolate 中運(yùn)行的, 它就是機(jī)器上的一個(gè)小空間, 具有自己的私有內(nèi)存塊和一個(gè)運(yùn)行著 Event Looper 的單個(gè)線程. 每個(gè) isolate 都是相互隔離的, 并不像線程那樣可以共享內(nèi)存. 一般情況下, 一個(gè) Dart 應(yīng)用只會(huì)在一個(gè) isolate 中運(yùn)行所有代碼, 但如果有特殊需要, 可以開啟多個(gè):
1忆某、創(chuàng)建 isolate (Dart API)
Dart 默認(rèn)提供了 Isolate.spawn(entryPoint, message) 用于開啟 isolate, 通過源碼可以知道形參 message 其實(shí)是 形參 entryPoint 對(duì)應(yīng)的函數(shù)執(zhí)行時(shí)需要的參數(shù)弃舒。
使用 Isolate.spawn(entryPoint, message) 開啟 isolate, 并指定要執(zhí)行的任務(wù):
import 'dart:isolate';
main(List<String> args) {
print("main start");
Isolate.spawn(calc, 100);
print("main end");
}
void calc(int count) {
var total = 0;
for (var i = 0; i < count; i++) {
total += i;
}
print(total);
}
2状原、isolate 通信 (單向)
isolate 間可以一起工作的唯一方法是通過來回傳遞消息. 一般情況下, 子isolate 會(huì)將運(yùn)行結(jié)果通過管道以消息的形式發(fā)送到 主isolate, 并在 主isolate 的 Event Looper 中處理該消息, 這時(shí)就需要借助 ReceivePort 來處理消息的傳遞了:
- 在啟動(dòng) 子isolate 時(shí), 將 主isolate 的發(fā)送管道(SendPort)作為參數(shù)傳遞給 子isolate.
- 子isolate 在執(zhí)行完畢時(shí), 可以利用管道(SendPort)給 主isolate 發(fā)送信息.
import 'dart:isolate';
main(List<String> args) async {
print("main start");
// 1. 創(chuàng)建管道
var receivePort = ReceivePort();
// 2. 創(chuàng)建isolate
Isolate isolate = await Isolate.spawn(foo, receivePort.sendPort);
// 3. 監(jiān)聽管道
receivePort.listen((message) {
print(message);
// 不再使用時(shí), 關(guān)閉管道
receivePort.close();
// 不再使用時(shí), 將 isolate 殺死
isolate.kill();
});
print("main end");
}
void foo(SendPort sendPort) {
sendPort.send("Hello lqr");
}
3苗踪、創(chuàng)建 isolate (Flutter API)
Flutter 提供了更為方便的開啟 isolate 的 API: compute() 函數(shù). 以下是示例代碼:
main(List<String> args) async {
int result = await compute(powerNum, 5);
print(result);
}
int powerNum(int num) {
return num * num;
}