以下內(nèi)容從官網(wǎng)得到:
https://webdev.dartlang.org/articles/performance/event-loop
Even-Looper
Dart是單線程模型,也就沒有了所謂的主線程/子線程之分。
Dart也是Event-Looper以及Event-Queue的模型伍纫,所有的事件都是通過EventLooper的依次執(zhí)行。
而Dart的Event Loop就是:
- 從EventQueue中獲取Event
- 處理Event
- 直到EventQueue為空
而這些Event包括了用戶輸入池充,點(diǎn)擊躯保,Timer,文件IO等
單線程模型
一旦某個(gè)Dart的函數(shù)開始執(zhí)行贩猎,它將執(zhí)行到這個(gè)函數(shù)結(jié)束熊户,也就是Dart的函數(shù)不會被其他Dart代碼打斷。
Dart中沒有線程的概念吭服,只有isolate嚷堡,每個(gè)isolate都是隔離的,并不會共享內(nèi)存。而一個(gè)Dart程序是在Main isolate的main函數(shù)開始蝌戒,而在Main函數(shù)結(jié)束后串塑,Main isolate線程開始一個(gè)一個(gè)(one by one)的開始處理Event Queue中的每一個(gè)Event。
Event Queue以及Microtask Queue
Dart中的Main Isolate只有一個(gè)Event Looper北苟,但是存在兩個(gè)Event Queue:Event Queue以及Microtask Queue
Microtask Queue存在的意義是:
希望通過這個(gè)Queue來處理稍晚一些的事情桩匪,但是在下一個(gè)消息到來之前需要處理完的事情。
當(dāng)Event Looper正在處理Microtask Queue中的Event時(shí)候友鼻,Event Queue中的Event就停止了處理了傻昙,此時(shí)App不能繪制任何圖形,不能處理任何鼠標(biāo)點(diǎn)擊彩扔,不能處理文件IO等等
Event-Looper挑選Task的執(zhí)行順序?yàn)椋?/p>
- 優(yōu)先全部執(zhí)行完Microtask Queue中的Event
- 直到Microtask Queue為空時(shí)妆档,才會執(zhí)行Event Queue中的Event
Dart中只能知道Event處理的先后順序,但是并不知道某個(gè)Event執(zhí)行的具體時(shí)間點(diǎn)借杰,因?yàn)樗奶幚砟P褪且粋€(gè)單線程循環(huán)过吻,而不是基于時(shí)鐘調(diào)度(即它的執(zhí)行只是按照Event處理完,就開始循環(huán)下一個(gè)Event蔗衡,而與Java中的Thread調(diào)度不一樣纤虽,沒有時(shí)間調(diào)度的概念),也就是我們既是指定另一個(gè)Delay Time的Task绞惦,希望它在預(yù)期的時(shí)間后開始執(zhí)行逼纸,它有可能不會在那個(gè)時(shí)間執(zhí)行,需要看是否前面的Event是否已經(jīng)Dequeue济蝉。
異步任務(wù)調(diào)度
當(dāng)有代碼可以在后續(xù)任務(wù)執(zhí)行的時(shí)候杰刽,有兩種方式,通過dart:async這個(gè)Lib中的API即可:
- 使用Future類王滤,可以將任務(wù)加入到Event Queue的隊(duì)尾
- 使用scheduleMicrotask函數(shù)贺嫂,將任務(wù)加入到Microtask Queue隊(duì)尾
當(dāng)使用EventQueue時(shí),需要考慮清楚雁乡,盡量避免microtask queue過于龐大第喳,否則會阻塞其他事件的處理
使用Future
一般常用的Future構(gòu)造函數(shù):
new Future((){
// doing something
});
而一般常用的還有當(dāng)有分治任務(wù)時(shí),需要將一個(gè)大任務(wù)拆成很多小任務(wù)一步步執(zhí)行時(shí)踱稍,就需要使用到Future.then函數(shù)來拆解任務(wù)
void main(){
new Future(() => futureTask) // 異步任務(wù)的函數(shù)
.then((m) => "futueTask execute result:$m") // 任務(wù)執(zhí)行完后的子任務(wù)
.then((m) => m.length) // 其中m為上個(gè)任務(wù)執(zhí)行完后的返回的結(jié)果
.then((m) => printLength(m))
.whenComplete(() => whenTaskCompelete); // 當(dāng)所有任務(wù)完成后的回調(diào)函數(shù)
}
int futureTask() {
return 21;
}
void printLength(int length) {
print("Text Length:$length");
}
void whenTaskCompelete() {
print("Task Complete");
}
當(dāng)任務(wù)需要延遲執(zhí)行時(shí)曲饱,可以使用new Future.delay來將任務(wù)延遲執(zhí)行,而如上所述珠月,只有當(dāng)Main isolate的Event Queue處于Idle的狀態(tài)時(shí)扩淀,才會延遲1s執(zhí)行,否則等待的時(shí)間會比1s長很多
new Future.delayed(const Duration(seconds: 1), () => futureTask);
當(dāng)需要做動畫的時(shí)候啤挎,不要使用Future驻谆,而需要使用animateFrame
PS:
- Future中的then并沒有創(chuàng)建新的Event丟到Event Queue中,而只是一個(gè)普通的Function Call,在FutureTask執(zhí)行完后胜臊,立即開始執(zhí)行
- 當(dāng)Future在then函數(shù)先已經(jīng)執(zhí)行完成了氛谜,則會創(chuàng)建一個(gè)task,將該task的添加到microtask queue中区端,并且該任務(wù)將會執(zhí)行通過then傳入的函數(shù)
- Future只是創(chuàng)建了一個(gè)Event值漫,將Event插入到了Event Queue的隊(duì)尾
- 使用Future.value構(gòu)造函數(shù)的時(shí)候,就會和第二條一樣织盼,創(chuàng)建Task丟到microtask Queue中執(zhí)行then傳入的函數(shù)
- Future.sync構(gòu)造函數(shù)執(zhí)行了它傳入的函數(shù)之后杨何,也會立即創(chuàng)建Task丟到microtask Queue中執(zhí)行
使用scheduleMicrotask
在最頂層的調(diào)用關(guān)系中,使用該函數(shù)即可
async.scheduleMicrotask(() => microtask());
void microtask(){
// doing something
}
使用isolate以及Worker
當(dāng)有計(jì)算很繁重的任務(wù)時(shí)沥邻,則需要使用isolate或者Worker來執(zhí)行危虱,以保持App對用戶操作的及時(shí)響應(yīng)。Isolate的實(shí)現(xiàn)可能是一個(gè)單獨(dú)的線程唐全,或者一個(gè)單獨(dú)的進(jìn)程埃跷,需要看Dart VM是如何實(shí)現(xiàn)的。