Node-單執行緒、事件驅動、非阻塞I/O
阿新 • • 發佈:2018-12-16
Nodejs既然這麼流行就肯定有它的博大精深之處,自然不是我這還沒入門的小白可以掌握的,我就簡單說一下目前自己的理解程度。
一、單執行緒、非阻塞I/O、事件驅動
這是nodejs的三個特點。
- 單執行緒
Nodejs是單執行緒,和多執行緒相比:
優點:可以避免系統分配多執行緒以及執行緒間通訊時的開銷,可以更高效的利用cpu,降低記憶體的耗用。
缺點:一旦出現錯誤會導致整個程式崩潰,不擅長大量的計算,無法利用多核cpu(貌似現在也有辦法) - 非阻塞I/O
非阻塞I/O從名字上便可以理解,為了提高程式的效能,更好的提高執行緒的利用率,儘量不讓執行緒空閒著。
比如我們想要讀取一個檔案,然後再進行一些操作,當然這些操作的前提條件是不需要這個檔案的資料,這個時候我們便可以讓系統的某個執行緒去讀取檔案,同時程式的主執行緒繼續執行下面的操作,程式並不會等待檔案讀取完畢才繼續執行,這就像我們常用的ajax - 事件驅動
Nodejs提供的絕大多數API都是基於事件的、非同步的風格,就是伺服器程式的入口也是從connect事件開始。
還是繼續上面的讀取檔案的例子,假如我要讀取一個檔案,然後要打印出檔案的內容,那麼讀取檔案便是一個事件(readFile),而列印的操作要在事件的回撥函式中執行。
在這裡又涉及到了事件佇列和事件迴圈:
程式主執行緒順序執行,當遇到一個事件時會將其新增進事件佇列,Nodejs底層的libuv庫(不要問我這是什麼鬼,底層的東西看著都嚇人)負責將事件佇列中不同的事件任務分配給不同的執行緒去執行,執行的結果再重新返回給使用者,這便是事件迴圈。
為什麼Nodejs是單執行緒的,卻在這裡又變成了多執行緒,其實Nodejs對外展示是單執行緒的,但內部其實是多執行緒的,Node本身的主執行緒主要就是起不斷往返排程的作用
二、例子更好理解
說了這麼多,比個例子吧。我在網上定了個外賣,老闆在店裡安排人給我派送,定完外賣之後開始打遊戲,正打著激烈的時候派送員來了,玩的正嗨呢,沒空開門,結果派送員在門外等了1一分鐘才去開門,至此我定外賣的這個過程也就結束了。
在這個例子中我就相當於主執行緒,我定了外賣後這個單子就會加入到店鋪的訂單列表,就相當於一個事件加入到了事件佇列,老闆就是這個libuv,他在店裡運籌帷幄安排人員給我做飯,然後送外賣,即分配執行緒執行事件任務,當送回來時如果我是空閒的我就會立刻開門收快遞,但是當時我正忙著(打遊戲很重要),所以派送員久等了一會,即事件執行之後的回撥函式是否會立即執行要看主執行緒是否空閒。
三、總結
- Node 表面上是單執行緒,其實內部仍然是多執行緒的,主執行緒起往返排程
- 單執行緒、事件驅動、非阻塞I/O,我的理解是事件驅動只是為了實現非阻塞的方式,非阻塞才是目的
作者:小弋呀
連結:https://www.jianshu.com/p/14bb2b4038d3
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。