js與Nodejs的單線程和異步--初探


Event Loop

  • Event Loop : 瀏覽器使用 Event Loop 來協調 DOM 事件、UI 渲染、腳本執行和網絡事件等。
  • Task Queue (Event Queue) :每當 DOM 事件、計時器事件或者網絡事件被觸發時,它們的回調函數和 Context 都會被壓入 Event Queue,而 Event Loop 則會從中取出回調函數並執行。

雖然JavaScript是單線程的(按順序執行的主線程),但維護事件隊列的是另一個線程(Event Loop)。每當某個事件被觸發,它的回調函數就會等待在這個隊列(Event Queue)里。

異步方法最主要有2點,一個是不阻塞當前代碼的執行,另一個是有回調方法。即異步方法運行完可以通知主線程。

Event Loop有browsing contexts和 workers兩種類型。一個event loop可以有一個或多個task queues來自同一個task source的所有tasks必須放入同一個task queue。

通常有4種task source:DOM manipulation task source,user interaction task source,networking task source和history traversal task source。

同一個task queue是按先進先出順序執行的。瀏覽器可以根據task queue中task source的不同,給予task queue不同的優先級。即由瀏覽器決定挑哪一個task queue中的隊首task執行。

 

      瀏覽器的三個常駐線程

瀏覽器是多線程的,它們在內核制控下相互配合以保持同步。一個瀏覽器至少實現三個常駐線程:JavaScript引擎線程,GUI渲染線程,瀏覽器事件觸發線程(UI線程)。

1) javascript引擎是基於事件驅動單線程執行的。JS引擎一直等待着event loop中任務的到來,然后加以處理(只有當前函數執行棧執行完畢,才會去任務隊列中取任務執行)。瀏覽器無論什么時候都只有一個JS線程在運行JS程序。

2) UI渲染線程負責渲染瀏覽器界面,當界面需要重繪(Repaint)或由於某種操作引發回流(reflow)時,該線程就會執行。但是 GUI渲染線程與JS引擎是互斥的,當JS引擎執行時GUI線程會被掛起,JS對頁面的操作即GUI的更新也會被保存在一個隊列中,等到JS引擎空閑時才有機會被執行。這就是JS阻塞頁面加載。

3) 事件觸發線程,當一個事件被觸發時該線程會把事件添加到任務隊列的隊尾,等待JS引擎的處理。這些事件可以來自JavaScript引擎當前執行的代碼塊調用setTimeout/ajax添加一個任務,也可以來自瀏覽器其他線程如鼠標點擊添加的任務。但由於JS的單線程關系,所有這些事件都得排隊等待JS引擎處理。

javascript要等主線程空了才會去查看子線程有沒有回調內容。異步的任務執行的順序是不固定的,主要看返回的速度。

function f() {
  console.log("foo");
  setTimeout(g, 0);
  console.log("baz");
  h();
}

function g() {
  console.log("bar");
}

function h() {
  console.log("blix");
}

f();
輸出的結果為:foo 、baz 、 blix 、bar

 

瀏覽器的多線程技術

Web Worker(可開啟獨立運行在瀏覽器后台的js環境)

 

Nodejs的異步任務執行流程

用戶寫的代碼是單線程的,但nodejs內部並不是單線程!

node.js的事件模型

Node.js不是用多個線程為每個請求執行工作的,相反而是它把所有工作添加到一個事件隊列中,然后有一個單獨線程,來循環提取隊列中的事件。事件循環線程抓取事件隊列中最上面的條目,執行它,然后抓取下一個條目。當執行長期運行或有阻塞I/O的代碼時,注意這里:它不會被阻塞,會繼續提取下一個事件,而對於被阻塞的事件Node.js會從線程池中取出一個線程來運行這個被阻塞的代碼,同時把當前事件本身和它的回調事件一同添加到事件隊列(callback嵌套callback)。

當Node.js事件隊列中的所有事件都被執行完成時,Node.js應用程序終止。

 

Nodejs架構

        NodeJS的顯著特點:異步機制、事件驅動。

點餐的廚房的例子:整個過程沒有阻塞新用戶的連接,也不需要維護連接。

基於這樣的機制,理論上陸續有用戶請求連接,NodeJS都可以進行響應,因此NodeJS能支持比Java、php程序更高的並發量。

雖然維護事件隊列也需要成本,再由於NodeJS是單線程,事件隊列越長,得到響應的時間就越長,並發量上去還是會力不從心。

RESTful API是NodeJS最理想的應用場景,可以處理數萬條連接,本身沒有太多的邏輯,只需要請求API,組織數據進行返回即可。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM