你以爲Node.js是單線程這個結論對嗎?

前言

一提到 Node.js ,我想你們都會想到它的一個特色,單線程。可是 Node.js 在運行的時候依賴 V8 這個宿主環境,難道在宿主環境中也是單線程嗎?請看正文解釋你這個疑惑。javascript

做者簡介:koala,專一完整的 Node.js 技術棧分享,從 JavaScript 到 Node.js,再到後端數據庫,祝您成爲優秀的高級 Node.js 工程師。【程序員成長指北】做者,Github 博客開源項目 github.com/koala-codin…html

Node.js 單線程誤區

開啓 Node.js 服務 Demo

const http = require('http');

const server = http.createServer();
server.listen(3000,()=>{
    process.title='程序員成長指北測試進程';
    console.log('進程id',process.pid)
})
複製代碼

看這段代碼,建立了http服務,開啓了一個進程,都說了Node.js是單線程,因此 Node 啓動後線程數應該爲 1,可是事實並不是如此,嗚嗚嗚。java

看活動監視器怎麼開啓7個線程呢?難道Javascript不是單線程不知道小夥伴們有沒有這個疑問?node

解釋一下這個緣由:git

Node 中最核心的是 v8 引擎,在 Node 啓動後,會建立 v8 的實例,這個實例是多線程的。程序員

  • 主線程:編譯、執行代碼。
  • 編譯/優化線程:在主線程執行的時候,能夠優化代碼。
  • 分析器線程:記錄分析代碼運行時間,爲 Crankshaft 優化代碼執行提供依據。
  • 垃圾回收的幾個線程。

因此你們常說的 Node 是單線程的指的是 JavaScript 的執行是單線程的(開發者編寫的代碼運行在單線程環境中),但 Javascript 的宿主環境,不管是 Node 仍是瀏覽器都是多線程的由於 libuv 中有線程池的概念存在的,libuv 會經過相似線程池的實現來模擬不一樣操做系統的異步調用,這對開發者來講是不可見的。github

V8中何時會建立額外進程

某些異步 IO 會佔用額外的線程

仍是上面那個例子,咱們在定時器執行的同時,去讀一個文件:數據庫

const fs = require('fs')
setInterval(() => {
    console.log(new Date().getTime())
}, 3000)

fs.readFile('./kaola.html', () => {})
複製代碼

線程數量變成了 11 個,這是由於在 Node 中有一些 IO 操做(DNS,FS)和一些 CPU 密集計算(Zlib,Crypto)會啓用 Node 的線程池,而線程池默認大小爲 4,由於線程數變成了 11。後端

手動更改線程池默認大小:

process.env.UV_THREADPOOL_SIZE = 64
複製代碼

修改線程池默認大小後,輕鬆把線程變成 71。瀏覽器

Libuv

Libuv 是一個跨平臺的異步 IO 庫,它結合了 UNIX 下的 libev 和 Windows 下的 IOCP 的特性,最先由 Node.js 的做者開發,專門爲 Node.js 提供多平臺下的異步IO支持。Libuv 自己是由 C++ 語言實現的,Node.js 中的非阻塞 IO 以及事件循環的底層機制都是由 libuv 實現的。

libuv架構圖

在 Windows 環境下,libuv 直接使用Windows的 IOCP 來實現異步IO。在 非Windows 環境下,libuv使用多線程(線程池Thread Pool)來模擬異步IO,這裏僅簡要提一下 libuv 中有線程池的概念,以後的文章會介紹 libuv 如何實現進程間通訊。

注意下面我要說的話:

Node的異步調用是由 libuv 來支持的,以上面的讀取文件的例子,讀文件實質的系統調用是由 libuv 來完成的,Node只是負責調用 libuv 的接口,等數據返回後再執行對應的回調方法。

總結

本篇文章對 Node.js 的單線程誤區作了講解,不過本篇文章只是 Node.js 高級進階之進程與線程的預熱篇,接下來的文章會 對 Node.js 的進程與線程作一個詳細講解,包括原理分析,child_process 模塊與 cluse r模塊,進程守護以及在真實項目中的 Node.js 多進程架構模型。

自我介紹:

koala 公衆號【程序員成長指北】做者 ,專一 完整的 Node.js 技術棧分享,從 JavaScript 到 Node.js,再到後端數據庫,祝您成爲優秀的高級 Node.js 工程師。

加入咱們一塊兒學習吧!

node學習交流羣

交流羣滿100人不能自動進羣, 請添加羣助手微信號:【coder_qi】備註node,自動拉你入羣。

相關文章
相關標籤/搜索