天天看點

Flutter開發指南之理論篇:Dart文法05(單線程模型,事件循環模型,Isolate)

總目錄

Flutter開發指南之理論篇:Dart文法01(資料類型,變量,函數)

Flutter開發指南之理論篇:Dart文法02(運算符,循環,異常)

Flutter開發指南之理論篇:Dart文法03(類,泛型)

Flutter開發指南之理論篇:Dart文法04(庫,異步,正規表達式)

Flutter開發指南之理論篇:Dart文法05(單線程模型,事件循環模型,Isolate)

Flutter開發指南之理論篇:Flutter基礎01(架構,設計思想)

 Dart是一門面向對象語言,它針對web 和移動裝置開發進行了優化,主要特點為:

一切皆對象!無論是數字,函數還是null,所有對象繼承自Object類;

聲明一個變量時可以不指定具體類型,Dart可以自動推斷類型;

Dart支援頂層函數,函數是一等對象,且函數可作為參數傳遞;

Dart使用<code>_</code>開頭表示私有屬性,沒有關鍵字<code>public</code>,<code>protected</code>和<code>private</code>;

1. 單線程模型

 衆所周知,在Java中使用<code>多線程</code>來處理并發任務,适量并合适地使用多線程,能夠極大地提高資源的使用率和程式運作效率,但是缺點也比較明顯,比如<code>過度開啟線程會帶來額外的資源和性能消耗</code>或<code>多線程共享記憶體容易出現死鎖</code>等。實際上,在APP的使用過程中,多數處理空閑狀态,并不需要進行密集或高并發的處理,是以從某些意義上來說,多線程顯得有點多餘。正是因為如此,Dart作為一種新的語言,通過引<code>單線程模型</code>很好地處理了并發任務對多線程的依賴。

 Dart是一種單線程語言,是以Dart程式沒有主線程和子線程之分,而在Dart中線程并不是指<code>Thread</code>,而是指<code>Isolate</code>。因為Dart沒有線程的概念,隻有<code>Isolate</code>,每個<code>Isolate</code>都是隔離的,并不會共享記憶體。所有的Dart代碼都是在<code>Isolate</code>中運作,它就像機器上的一個小空間,具有自己的私有記憶體塊和一個運作着<code>事件循環模型</code>的單線程。也就是說,一旦某個Dart函數開始執行,它将執行到這個函數的結束而不被其他Dart代碼打斷,這就是單線程的特性。

Flutter開發指南之理論篇:Dart文法05(單線程模型,事件循環模型,Isolate)

 預設情況下,Dart程式隻有一個<code>Isolate</code>(未自己建立的情況下),而這個<code>Isolate</code>就是<code>Main Isolate</code>。也就是說,一個Dart程式是從<code>Main Isolate</code>的main函數開始的,而在main函數結束後,<code>Main isolate</code>線程開始一個一個處理事件循環模型隊列中的每一<code>事件(Event)</code>。上圖描述的就是<code>Main Isolate</code>的消息循環模型。

 也許你會問,既然Dart是一種單線程語言,那麼是不是就意味着Dart無法并發處理異步任務了?此言差矣。前面說到,所有的Dart程式都在<code>Isolate</code>中運作,每個<code>Isolate</code>擁有自己的私有記憶體塊和一個<code>事件循環模型</code>,其中,<code>事件循環模型</code>就是用來處理各種事件,比如點輸入/輸出,點選,定時器以及異步任務等。下圖描述了一個<code>Isolate</code>的<code>事件循環模型</code>的整個流程:

Flutter開發指南之理論篇:Dart文法05(單線程模型,事件循環模型,Isolate)

 從上圖可知,Dart事件循環機制由<code>一個消息循環(event looper)</code>和<code>兩個消息隊列</code>構成,其中,兩個消息隊列是指<code>事件隊列(event queue)</code>和<code>微任務隊列(Microtask queue)</code>。該機制運作原理為:

首先,Dart程式從main函數開始運作,待main函數執行完畢後,event looper開始工作;

然後,event looper優先周遊執行Microtask隊列所有事件,直到Microtask隊列為空;

接着,event looper才周遊執行Event隊列中的所有事件,直到Event隊列為空;

最後,視情況退出循環。

 為了進一步了解,我們解釋下上述三個概念:

(1)消息循環(<code>Event Looper</code>)

 顧名思義,消息循環就是指一個永不停歇且不能阻塞的循環,它将不停的嘗試從<code>微任務隊列</code>和<code>事件隊列</code>中擷取事件(event)進行處理,而這些Event包括了使用者輸入,點選,Timer,檔案IO等。

Flutter開發指南之理論篇:Dart文法05(單線程模型,事件循環模型,Isolate)

(2)事件隊列(<code>Event queue</code>)

 該隊列的事件來源于<code>外部事件</code>和<code>Future</code>,其中,<code>外部事件</code>主要包括I/O,手勢,繪制,計時器和isolate互相通信的message等,而<code>Future</code>主要是指使用者自定義的異步任務,通過建立Future類執行個體來向事件隊列添加事件。需要注意的是,當Event looper正在處理<code>Microtask Queue</code>時,<code>Event queue</code>會被阻塞,此時APP将無法進行UI繪制,響應使用者輸入和I/O等事件。下列示例示範了向<code>Event queue</code>中添加一個異步任務事件:

(3)微任務隊列(<code>Microtask queue</code>)

 該隊列的事件來源與目前isolate的内部或通過<code>scheduleMicrotask</code>函數建立,Microtask一般用于非常短的内部異步動作,并且任務量非常少,如果微任務非常多,就會造成<code>Event queue</code>排不上隊,會阻塞<code>Event queue</code>的執行造成應用ANR,因為<code>Microtask queue</code>的優先級高于<code>Event queue</code>。是以,大多數情況下的任務優先考慮使用<code>Event queue</code>,不到萬不得已不要使用<code>Microtask queue</code>。下列示例示範了兩個事件隊列執行情況:

2. Isolate

 大多數計算機中,甚至在移動平台上,都在使用多核CPU。 為了有效利用多核性能,開發者一般使用共享記憶體資料來保證多線程的正确執行。 然而多線程共享資料通常會導緻很多潛在的問題,并導緻代碼運作出錯。Dart作為一種新語言,為了緩解上述問題,提出了<code>Isolate(隔離區)</code>的概念,即Dart沒有線程的概念,隻有<code>Isolate</code>,所有的Dart代碼都是在<code>Isolate</code>中運作,它就像是機器上的一個小空間,具有自己的私有記憶體堆和一個運作着Event Looper的單個線程。

Flutter開發指南之理論篇:Dart文法05(單線程模型,事件循環模型,Isolate)

 通常,一個Dart應用對應着一個<code>Main Isolate</code>,且應用的入口即為該Isolate的main函數。當然,我們也可以建立其它的<code>Isolate</code>,由于<code>Isolate</code>的記憶體堆是私有的,是以這些<code>Isolate</code>的記憶體都不會被其它<code>Isolate</code>通路。假如不同的<code>Isolate</code>需要通信(單向/雙向),就隻能通過向對方的事件循環隊列裡寫入任務,并且它們之間的通訊方式是通過<code>port(端口)</code>實作的,其中,Port又分為<code>receivePort(接收端口)</code>和<code>sendPort(發送端口)</code>,它們是成對出現的。Isolate之間通信過程:

首先,目前<code>Isolate</code>建立一個<code>ReceivePort</code>對象,并獲得對應的<code>SendPort</code>對象;

其次,建立一個新的<code>Isolate</code>,并實作新<code>Isolate</code>要執行的異步任務,同時,将目前Isolate的SendPort對象傳遞給新的Isolate,以便新Isolate使用這個SendPort對象向原來的Isolate發送事件;

第三,調用目前Isolate#receivePort的listen方法監聽新的Isolate傳遞過來的資料。Isolate之間什麼資料類型都可以傳遞,不必做任何标記。

最後,消息傳遞完畢,關閉新建立的Isolate。

示例代碼如下(Isolate單向通信):

 執行結果:

3. 參考文獻

1. Dart asynchronous programming: Isolates and event loops

2. Futures - Isolates - Event Loop

3. Flutter 真異步

Flutter開發指南之理論篇:Dart文法05(單線程模型,事件循環模型,Isolate)

繼續閱讀