Nodejs既然這么流行就肯定有它的博大精深之處,自然不是我這還沒入門的小白可以掌握的璃谨,我就簡單說一下目前自己的理解程度沙庐。
一、單線程佳吞、非阻塞I/O拱雏、事件驅動
這是nodejs的三個特點。
- 單線程
Nodejs是單線程底扳,和多線程相比:
優(yōu)點:可以避免系統(tǒng)分配多線程以及線程間通信時的開銷铸抑,可以更高效的利用cpu,降低內存的耗用衷模。
缺點:一旦出現錯誤會導致整個程序崩潰鹊汛,不擅長大量的計算,無法利用多核cpu(貌似現在也有辦法) - 非阻塞I/O
非阻塞I/O從名字上便可以理解阱冶,為了提高程序的性能刁憋,更好的提高線程的利用率,盡量不讓線程空閑著木蹬。
比如我們想要讀取一個文件至耻,然后再進行一些操作,當然這些操作的前提條件是不需要這個文件的數據,這個時候我們便可以讓系統(tǒng)的某個線程去讀取文件尘颓,同時程序的主線程繼續(xù)執(zhí)行下面的操作走触,程序并不會等待文件讀取完畢才繼續(xù)執(zhí)行,這就像我們常用的ajax - 事件驅動
Nodejs提供的絕大多數API都是基于事件的疤苹、異步的風格互广,就是服務器程序的入口也是從connect事件開始。
還是繼續(xù)上面的讀取文件的例子痰催,假如我要讀取一個文件兜辞,然后要打印出文件的內容迎瞧,那么讀取文件便是一個事件(readFile)夸溶,而打印的操作要在事件的回調函數中執(zhí)行。
在這里又涉及到了事件隊列和事件循環(huán):
程序主線程順序執(zhí)行凶硅,當遇到一個事件時會將其添加進事件隊列缝裁,Nodejs底層的libuv庫(不要問我這是什么鬼,底層的東西看著都嚇人)負責將事件隊列中不同的事件任務分配給不同的線程去執(zhí)行足绅,執(zhí)行的結果再重新返回給用戶捷绑,這便是事件循環(huán)。
為什么Nodejs是單線程的氢妈,卻在這里又變成了多線程粹污,其實Nodejs對外展示是單線程的,但內部其實是多線程的首量,Node本身的主線程主要就是起不斷往返調度的作用
二壮吩、例子更好理解
說了這么多,比個例子吧加缘。我在網上定了個外賣鸭叙,老板在店里安排人給我派送,定完外賣之后開始打游戲拣宏,正打著激烈的時候派送員來了沈贝,玩的正嗨呢,沒空開門勋乾,結果派送員在門外等了1一分鐘才去開門宋下,至此我定外賣的這個過程也就結束了。
在這個例子中我就相當于主線程辑莫,我定了外賣后這個單子就會加入到店鋪的訂單列表学歧,就相當于一個事件加入到了事件隊列,老板就是這個libuv摆昧,他在店里運籌帷幄安排人員給我做飯撩满,然后送外賣,即分配線程執(zhí)行事件任務,當送回來時如果我是空閑的我就會立刻開門收快遞伺帘,但是當時我正忙著(打游戲很重要)昭躺,所以派送員久等了一會,即事件執(zhí)行之后的回調函數是否會立即執(zhí)行要看主線程是否空閑伪嫁。
三领炫、總結
- Node 表面上是單線程,其實內部仍然是多線程的张咳,主線程起往返調度
- 單線程帝洪、事件驅動、非阻塞I/O,我的理解是事件驅動只是為了實現非阻塞的方式脚猾,非阻塞才是目的