深入淺析Node.js 中的多執行緒與多進程
Node.js 是一個免費的跨平台JavaScript 執行時間環境,儘管它本質上是單執行緒的,但可以在後台使用多個執行緒來執行異步代碼。
由於 Node.js 的非阻塞性質,不同的執行緒執行不同的回呼,這些回呼首先委託給事件循環。 Node.js 運行時負責處理這一切。 【影片教學推薦:node js教學 】
為什麼要使用NodeJS?
JavaScript 最初是作為單執行緒程式語言建構的,僅在 Web 瀏覽器中執行。這意味著在一個過程中,只有一組指令能夠在給定的時間執行。
僅在目前程式碼區塊的執行完成後,才會移至下一個程式碼區塊。但是,JavaScript 的單執行緒性質使實作變得容易。
最初,JavaScript 對於僅用於在網站上新增少量互動。所以並沒有對多執行緒的需求。但時代已經改變了,使用者要求也越來越高,JavaScript 已成為「Web 上流行的程式語言」。
多執行緒現在變得很普遍。由於 JavaScript 是單線程語言,因此無法在其中實作多線程。幸運的是,在這種情況下,有一個很好的解決方法:Node.js。
Node.js 框架並不少,這要歸功於 JavaScript 執行時期環境(尤其是 JavaScript)的普遍流行。在繼續本文之前,讓我們先了解一些關於Node.js 的重要觀點:
- 可以用send 函數將訊息從子進程傳遞到其他子進程和主進程
- 支持fork 多個進程
- 主進程和子進程之間不共享狀態
為什麼要fork 進程?
在兩種情況下,我們需要fork 一個流程:
- 透過將任務委派給其他進程來提高速度
- 用於釋放記憶體和卸載單個進程
可以將資料傳送到子進程,也可以將其送回。
Node.js 的方式
Node.js 使用兩種類型的線程:
- 透過事件循環處理主線程,
- 工作池中有許多輔助執行緒
事件循環負責取得回呼或函數,並將其註冊以供將來執行。它與正確的 JavaScript 程式碼在同一線程中運行。一旦 JavaScript 操作阻塞了線程,事件循環也會被阻塞。
工作池是一個執行模型,負責產生和處理不同的執行緒。它會同步執行任務,然後將結果傳回事件循環,最後事件循環將結果提供給回呼。
總而言之,工作池負責非同步 I/O 操作,也就是與系統磁碟和網路的互動。像 fs 和 crypto 這樣的模組是使用工作池的主要模組。
由於工作池是在 libuv 函式庫中實現的,Node.js 在 JS 和 C 之間進行內部通訊時會稍有延遲。不過這幾乎是不可察覺的。
一切都很好,直到我們遇到同步執行複雜操作的要求。任何需要大量時間執行的函數都會導致主執行緒阻塞。
如果程式具有多個佔用大量 CPU 的函數,將會導致伺服器吞吐量的顯著下降。在最壞的情況下,伺服器將會失去回應,並且無法將任務委派給工作池。
諸如 AI、大數據和機器學習之類的領域無法從 Node.js 中受益,因為這些操作阻塞了主線程,並使伺服器失去回應。但這隨著 Node.js v10.5.0 的到來而改變,該版本增加了對多執行緒的支援。
並發和 CPU 綁定任務的挑戰
在 JavaScript 中建立並發可能很困難。允許多個執行緒存取相同的記憶體會導致競爭狀態,這不僅使故障難以重現,而且解決起來也很困難。
Node.js 最初被實作為基於非同步 I/O 的伺服器端平台。透過簡單地消除線程需求,這使很多事情變得容易。是的,Node.js 程式是單線程的,但不是典型的方式。
我們可以在 Node.js 中並行運行,但不需要建立執行緒。作業系統和虛擬機器共同並行使用 I/O,然後在需要將資料傳回 JavaScript 程式碼時,JS 程式碼在單一執行緒中運行。
除 JS 程式碼外,所有內容均在 Node.js 中並行運行。與非同步區塊不同,JS 的同步區塊總是一次執行一次。與程式碼執行相比,等待 JS 中產生 I/O 事件所話費的時間要多得多。
Node.js 程式僅呼叫所需的函數或回調,而不會阻止其他程式碼的執行。最初 JavaScript 和 Node.js 都不打算處理 CPU 密集或 CPU 綁定的任務。
當程式碼最少時,執行將會是敏捷的。但是計算量越大,執行速度就越慢。
如果你仍然嘗試在 JS 和 Node 中完成 CPU 密集型任務,那麼將會使瀏覽器中的 UI 凍結並對所有 I/O 事件進行排隊處理。儘管如此,我們已經走了很遠。現在有了 worker_threads 模組。
worker_threads 模組讓多執行緒變得簡單
Node.js v10.5.0 於 2018 年 6 月發布,引入了 worker_threads 模組。它有助於在流行的 JavaScript 運行時環境中實現並發。此模組允許創建功能齊全的多線程 Node.js 應用。
從技術上講,工作執行緒是在單獨的執行緒中產生的一些程式碼。要開始使用輔助線程,需要先導入 worker_threads 模組。之後需要建立 Worker 類別的實例以建立工作執行緒。
在建立Worker 類別的實例時,有兩個參數:
- 第一個參數提供副檔名.js 或.mjs 的檔案路徑,其中包含工作程式執行緒的程式碼,
- 第二個參數提供了一個包含workerData 屬性的對象,該屬性包含工作執行緒開始執行時將存取的資料
輔助執行緒能夠調度多個訊息事件。因此,回呼方法優先於傳回 promise。
工作執行緒之間的通訊是基於事件的,即偵聽器設定為在工作執行緒發送事件後立即呼叫。最常見的 4 個事件是:
worker.on('error', (error) => {});
- 當工作執行緒中有未捕獲的例外狀況時發出。接下來工作執行緒終止,並且該錯誤可以作為回呼中的第一個參數使用。
worker.on('exit', (exitCode) => {})
- 當輔助執行緒退出時發出。如果在工作執行緒中呼叫了
process.exit()
,則會將 exitCode 提供給回呼。如果worker.terminate()
終止工作線程,則程式碼為 1。
worker.on('message', (data) => {});
- 當工作執行緒將資料傳送到父執行緒時發出。
worker.on('online', () => {});
- 當工作執行緒停止解析 JS 程式碼並開始執行時發出。儘管不常用,但 online 事件在特定情況下可能會提供更多資訊。
使用工作執行緒的方式
有兩種使用工作執行緒的方法:
- #方法1 – 涉及產生工作執行緒的方法:
- #方法1 – 涉及產生工作線程,執行其程式碼並將結果發送到父線程。此方法需要每次為新任務從頭建立新的 worker 執行緒。
– 涉及產生 worker 執行緒並為訊息事件設定偵聽器。每次觸發該訊息時,輔助線程都會執行程式碼,並將結果傳回父線程。輔助線程保持活動狀態,以備將來使用。
方法 2 也稱為工作池。這是因為該方法涉及創建 worker 的工作池,先讓他們等待,並在需要時去調度訊息事件來執行任務。 由於從頭開始建立工作執行緒需要建立虛擬機器以及解析和執行程式碼,因此- 官方 Node.js 文件
- 建議採用方法 2。此外,方法 2 更為實用,比方法 1 更有效。 worker_threads 模組中可用的重要屬性
- isMainThread – 當不在工作執行緒內操作時,此屬性為 true。如果需要,則可以在 worker 檔案的開頭包含一個簡單的 if 語句。這樣可以確保它僅作為工作執行緒運行。
- parentPort – MessagePort 的實例,用於與父執行緒進行通訊。
- threadId – 指派給工作執行緒的唯一識別碼。
– 包含在 worker 執行緒的建構子中的資料。
Node.js 中的多進程為了讓 Node.js 利用多核心系統的功能,可以用一些行程。在流行的 javascript 運行時環境中有稱被為 cluster 的模組,該模組提供對多進程的支援。 使用 cluster 模組可以產生多個子進程,這些子進程可以共用一個公共連接埠。當子進程投入使用時,使用 NodeJS 的系統可以處理更大的工作量。 網路已成為全球數以百萬計公司的首選平台。因此,為使企業發揮最大潛力,並在此過程中脫穎而出,必須擁有強大的網路形象。 這一切都始於一個強大而直覺的網站。要打造一個完美無瑕的網站,重要的是選擇最佳的前端和後端技術。儘管本質上是單線程的,但 Node.js 是開發後端 Web 服務
的首選。 儘管有大量的後端多執行緒選擇,知名公司還是喜歡 Node.js。這是因為 Node.js 提供了在 JavaScript 中使用多執行緒的變通方法,而 JavaScript 已經是「Web上最受歡迎的程式語言」。 ######總結######worker_threads 模組提供了一種在 Node.js 程式中實作多執行緒的簡單方法。透過將繁重的計算委派給工作線程,可以顯著提高伺服器的吞吐量。 ###借助對多執行緒的支持,Node.js 將繼續吸引越來越多的來自 AI、大數據和機器學習等計算密集型領域的開發人員、工程師和其他專業人員。
英文原文網址:https://flatlogic.com/blog/multi-threading-and-multiple-process-in-node-js/
為了保證的可讀性,本文採意譯而非直譯。
更多程式相關知識,可存取:程式設計教學! !
以上是深入淺析Node.js 中的多執行緒與多進程的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

基於無阻塞、事件驅動建立的Node服務,具有記憶體消耗低的優點,非常適合處理海量的網路請求。在海量請求的前提下,就需要考慮「記憶體控制」的相關問題了。 1. V8的垃圾回收機制與記憶體限制 Js由垃圾回收機

文件模組是對底層文件操作的封裝,例如文件讀寫/打開關閉/刪除添加等等文件模組最大的特點就是所有的方法都提供的**同步**和**異步**兩個版本,具有sync 字尾的方法都是同步方法,沒有的都是異

事件循環是 Node.js 的基本組成部分,透過確保主執行緒不被阻塞來實現非同步編程,了解事件循環對建立高效應用程式至關重要。以下這篇文章就來帶大家深入了解Node中的事件循環 ,希望對大家有幫助!

node無法用npm指令是因為沒有正確配置環境變量,其解決方法是:1、開啟“系統屬性”;2、找到“環境變數”->“系統變數”,然後編輯環境變數;3、找到nodejs所在的資料夾;4、點選「確定」即可。

Stream作業是Java8推出的一大亮點!雖然java.util.stream很強大,但還是有很多開發者在實際工作中很少使用,其中吐槽最多的一個原因就是不好調試,一開始確實是這樣,因為stream這樣的流式操作在DEBUG的時候,是一行程式碼,直接下一步的時候,其實一下就過了好多操作,這樣我們就很難判斷到底是裡面的哪一行出了問題。外掛:JavaStreamDebugger如果你用的IDEA版本比較新的話,這個插件已經是自備的了,就不需要安裝了。如果還沒安裝的話,就手動安裝一下,然後繼續下面

一開始的時候 JS 只在瀏覽器端運行,對於 Unicode 編碼的字串容易處理,但對於二進位和非 Unicode 編碼的字串處理困難。並且二進制是電腦最底層的資料格式,視訊/音訊/程式/網路包

java8的stream取maxpublicstaticvoidmain(String[]args){Listlist=Arrays.asList(1,2,3,4,5,6);Integermax=list.stream().max((a,b)->{if (a>b){return1;}elsereturn-1;}).get();System.out.println(max);}注意點:這裡判斷大小是透過正負數和0值。而不是直接寫成if(a>b){returna;}elseretur
