一提到 Node.js ,我想你們都會想到它的一個特色,單線程。可是 Node.js 在運行的時候依賴 V8 這個宿主環境,難道在宿主環境中也是單線程嗎?請看正文解釋你這個疑惑。javascript
做者簡介:koala,專一完整的 Node.js 技術棧分享,從 JavaScript 到 Node.js,再到後端數據庫,祝您成爲優秀的高級 Node.js 工程師。【程序員成長指北】做者,Github 博客開源項目 github.com/koala-codin…html
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 的實例,這個實例是多線程的。程序員
因此你們常說的 Node 是單線程的指的是 JavaScript 的執行是單線程的(開發者編寫的代碼運行在單線程環境中),但 Javascript 的宿主環境,不管是 Node 仍是瀏覽器都是多線程的由於 libuv 中有線程池的概念存在的,libuv 會經過相似線程池的實現來模擬不一樣操做系統的異步調用,這對開發者來講是不可見的。github
仍是上面那個例子,咱們在定時器執行的同時,去讀一個文件:數據庫
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 是一個跨平臺的異步 IO 庫,它結合了 UNIX 下的 libev 和 Windows 下的 IOCP 的特性,最先由 Node.js 的做者開發,專門爲 Node.js 提供多平臺下的異步IO支持。Libuv 自己是由 C++ 語言實現的,Node.js 中的非阻塞 IO 以及事件循環的底層機制都是由 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 工程師。
加入咱們一塊兒學習吧!
交流羣滿100人不能自動進羣, 請添加羣助手微信號:【coder_qi】備註node,自動拉你入羣。