node.js默認(rèn)是單線程的,因?yàn)镴avaScript引擎的關(guān)系,node.js采用的是單線程異步非阻塞的模式,一個(gè)nodejs無(wú)法利用多核資源;但是可以有第三方庫(kù)提供多線程的支持,只是主線程是單線程,主線程中的操作是同步阻塞的。
本教程操作環(huán)境:windows10系統(tǒng)、nodejs 12.19.0版本、Dell G3電腦。
node.js是單線程的嗎
node.js默認(rèn)是單線程,node.js采用單線程異步非阻塞模式。
node.js采用單線程異步非阻塞模式。它的單線程指的是自身Javascript運(yùn)行環(huán)境的單線程,Node.js并沒(méi)有給Javascript執(zhí)行時(shí)創(chuàng)建新線程的能力,通過(guò)Libuv以及它的事件循環(huán)來(lái)實(shí)現(xiàn)異步。
Node 只是主線程是單線程,主線程中的操作是同步阻塞的。但它把所有需要異步的操作扔給了IO線程池,主線程通過(guò)一定的事件輪詢機(jī)制與IO線程池交互得到異步數(shù)據(jù)。
node.js的性能不是最高的,因?yàn)閖avascript引擎的關(guān)系,node.js默認(rèn)是單線程,一個(gè)node.js應(yīng)用無(wú)法利用多核資源。
不過(guò)有第三方庫(kù)提供多線程支持,但不是無(wú)縫的。node.js是解決I/O瓶頸的(相對(duì)于傳統(tǒng)技術(shù),同步阻塞調(diào)用浪費(fèi)線程),它并沒(méi)有提高I/O速度,只是資源調(diào)度更高效。如果I/O速度不解決,node.js只能說(shuō)能同時(shí)處理好多request,但每個(gè)request的響應(yīng)時(shí)間還是那么長(zhǎng),甚至更長(zhǎng)。
Node 是單線程,那它是如何處理高并發(fā)請(qǐng)求的?
依靠事件驅(qū)動(dòng)。
每個(gè)Node.js進(jìn)程只有一個(gè)主線程在執(zhí)行程序代碼,形成一個(gè)執(zhí)行棧(execution context stack)。
主線程之外,還維護(hù)了一個(gè)"事件隊(duì)列"(Event queue)。當(dāng)用戶的網(wǎng)絡(luò)請(qǐng)求或者其它的異步操作到來(lái)時(shí),node都會(huì)把它放到Event Queue之中,此時(shí)并不會(huì)立即執(zhí)行它,代碼也不會(huì)被阻塞,繼續(xù)往下走,直到主線程代碼執(zhí)行完畢。
主線程代碼執(zhí)行完畢完成后,然后通過(guò)Event Loop,也就是事件循環(huán)機(jī)制,開(kāi)始到Event Queue的開(kāi)頭取出第一個(gè)事件,從線程池中分配一個(gè)線程去執(zhí)行這個(gè)事件,接下來(lái)繼續(xù)取出第二個(gè)事件,再?gòu)木€程池中分配一個(gè)線程去執(zhí)行,然后第三個(gè),第四個(gè)。主線程不斷的檢查事件隊(duì)列中是否有未執(zhí)行的事件,直到事件隊(duì)列中所有事件都執(zhí)行完了,此后每當(dāng)有新的事件加入到事件隊(duì)列中,都會(huì)通知主線程按順序取出交EventLoop處理。當(dāng)有事件執(zhí)行完畢后,會(huì)通知主線程,主線程執(zhí)行回調(diào),線程歸還給線程池。
主線程不斷重復(fù)上面的第三步。
NodeJs 單線程只是一個(gè)主線程,本質(zhì)上的異步操作還是由線程池完成的,node將所有的阻塞操作都交給了內(nèi)部的線程池去實(shí)現(xiàn),本身只負(fù)責(zé)不斷的往返調(diào)度,并沒(méi)有進(jìn)行真正的I/O操作,從而實(shí)現(xiàn)異步非阻塞I/O,這便是node單線程和事件驅(qū)動(dòng)的精髓之處了。
推薦學(xué)習(xí):《nodejs視頻教程》