以下內容從官網得到:
https://webdev.dartlang.org/articles/performance/event-loop
Even-Looper
Dart是單線程模型,也就沒有了所謂的主線程/子線程之分。
Dart也是Event-Looper以及Event-Queue的模型,所有的事件都是通過EventLooper的依次執行。
而Dart的Event Loop就是:
- 從EventQueue中獲取Event
- 處理Event
- 直到EventQueue為空
而這些Event包括了用戶輸入,點擊,Timer,文件IO等
單線程模型
一旦某個Dart的函數開始執行,它將執行到這個函數結束,也就是Dart的函數不會被其他Dart代碼打斷。
Dart中沒有線程的概念,只有isolate,每個isolate都是隔離的,并不會共享內存。而一個Dart程序是在Main isolate的main函數開始,而在Main函數結束后,Main isolate線程開始一個一個(one by one)的開始處理Event Queue中的每一個Event。
Event Queue以及Microtask Queue
Dart中的Main Isolate只有一個Event Looper,但是存在兩個Event Queue:Event Queue以及Microtask Queue
Microtask Queue存在的意義是:
希望通過這個Queue來處理稍晚一些的事情,但是在下一個消息到來之前需要處理完的事情。
當Event Looper正在處理Microtask Queue中的Event時候,Event Queue中的Event就停止了處理了,此時App不能繪制任何圖形,不能處理任何鼠標點擊,不能處理文件IO等等
Event-Looper挑選Task的執行順序為:
- 優先全部執行完Microtask Queue中的Event
- 直到Microtask Queue為空時,才會執行Event Queue中的Event
Dart中只能知道Event處理的先后順序,但是并不知道某個Event執行的具體時間點,因為它的處理模型是一個單線程循環,而不是基于時鐘調度(即它的執行只是按照Event處理完,就開始循環下一個Event,而與Java中的Thread調度不一樣,沒有時間調度的概念),也就是我們既是指定另一個Delay Time的Task,希望它在預期的時間后開始執行,它有可能不會在那個時間執行,需要看是否前面的Event是否已經Dequeue。
異步任務調度
當有代碼可以在后續任務執行的時候,有兩種方式,通過dart:async這個Lib中的API即可:
- 使用Future類,可以將任務加入到Event Queue的隊尾
- 使用scheduleMicrotask函數,將任務加入到Microtask Queue隊尾
當使用EventQueue時,需要考慮清楚,盡量避免microtask queue過于龐大,否則會阻塞其他事件的處理
使用Future
一般常用的Future構造函數:
new Future((){
// doing something
});
而一般常用的還有當有分治任務時,需要將一個大任務拆成很多小任務一步步執行時,就需要使用到Future.then函數來拆解任務
void main(){
new Future(() => futureTask) // 異步任務的函數
.then((m) => "futueTask execute result:$m") // 任務執行完后的子任務
.then((m) => m.length) // 其中m為上個任務執行完后的返回的結果
.then((m) => printLength(m))
.whenComplete(() => whenTaskCompelete); // 當所有任務完成后的回調函數
}
int futureTask() {
return 21;
}
void printLength(int length) {
print("Text Length:$length");
}
void whenTaskCompelete() {
print("Task Complete");
}
當任務需要延遲執行時,可以使用new Future.delay來將任務延遲執行,而如上所述,只有當Main isolate的Event Queue處于Idle的狀態時,才會延遲1s執行,否則等待的時間會比1s長很多
new Future.delayed(const Duration(seconds: 1), () => futureTask);
當需要做動畫的時候,不要使用Future,而需要使用animateFrame
PS:
- Future中的then并沒有創建新的Event丟到Event Queue中,而只是一個普通的Function Call,在FutureTask執行完后,立即開始執行
- 當Future在then函數先已經執行完成了,則會創建一個task,將該task的添加到microtask queue中,并且該任務將會執行通過then傳入的函數
- Future只是創建了一個Event,將Event插入到了Event Queue的隊尾
- 使用Future.value構造函數的時候,就會和第二條一樣,創建Task丟到microtask Queue中執行then傳入的函數
- Future.sync構造函數執行了它傳入的函數之后,也會立即創建Task丟到microtask Queue中執行
使用scheduleMicrotask
在最頂層的調用關系中,使用該函數即可
async.scheduleMicrotask(() => microtask());
void microtask(){
// doing something
}
使用isolate以及Worker
當有計算很繁重的任務時,則需要使用isolate或者Worker來執行,以保持App對用戶操作的及時響應。Isolate的實現可能是一個單獨的線程,或者一個單獨的進程,需要看Dart VM是如何實現的。