一、核心結論
Node.js 的 worker_threads
模塊實現的是 并行計算 ,而非傳統意義上的“并發”。其通過操作系統級線程實現多核 CPU 的并行執行,同時保留 Node.js 單線程事件循環的并發模型。
二、關鍵概念解析
1. 并發(Concurrency) vs 并行(Parallelism)
-
并發:
- 指系統同時處理多個任務的能力,但任務可能交替執行(如單核 CPU 通過時間片輪轉)。
- Node.js 主線程 的事件循環是典型的并發模型,通過非阻塞 I/O 和事件隊列實現。
-
并行:
- 指多個任務同時執行,需多核 CPU 支持,每個任務運行在獨立核心上。
worker_threads
通過創建操作系統級線程實現并行計算。
2. Node.js 的線程模型
-
主線程:
- 單線程,運行事件循環,處理 I/O 和事件回調。
- 阻塞主線程會導致整個進程卡頓。
-
Worker 線程:
- 每個 Worker 線程是獨立的 JavaScript 運行時,擁有自己的事件循環和堆內存。
- 線程由操作系統的系統線程支持,可綁定到不同 CPU 核心,實現并行執行。
三、worker_threads
的并行機制
1. 多核利用
-
默認線程數:
- Node.js 根據 CPU 核心數自動創建線程池(通常等于核心數)。
- 例如,4 核 CPU 默認創建 4 個線程,每個線程綁定到一個核心。
-
任務分配:
- 主線程通過
Worker
類創建子線程,并將任務通過postMessage
分發。 - 子線程執行任務后,通過
parentPort.postMessage
返回結果。
- 主線程通過
2. 線程調度
-
操作系統調度:
- Worker 線程由操作系統調度到不同 CPU 核心,實現真正的并行執行。
- 線程間通過
SharedArrayBuffer
或消息傳遞通信,避免阻塞主線程。
-
示例:并行計算斐波那契數列
// main.js const { Worker } = require('worker_threads'); const numCPUs = require('os').cpus().length;for (let i = 0; i < numCPUs; i++) {const worker = new Worker('./fibonacciWorker.js');worker.postMessage(40); // 每個線程計算第40個斐波那契數 }
// fibonacciWorker.js const { parentPort } = require('worker_threads');function fibonacci(n) {return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2); }parentPort.on('message', (n) => {const result = fibonacci(n);parentPort.postMessage(result); });
四、對比傳統并發模型
1. 事件循環(主線程)
-
特點:
- 單線程,通過非阻塞 I/O 和事件隊列實現高并發。
- 適合 I/O 密集型任務(如網絡請求、文件操作)。
-
局限:
- CPU 密集型任務會阻塞事件循環,導致其他任務無法執行。
2. Worker 線程(并行計算)
-
特點:
- 多線程,利用多核 CPU 并行執行 CPU 密集型任務。
- 線程間通過消息傳遞或共享內存通信,避免阻塞主線程。
-
適用場景:
- 大型計算(如加密、圖像處理、機器學習)。
- 并行化數據庫查詢或數據處理任務。
五、性能監控與驗證
1. 監控 CPU 核心利用率
-
Linux:
top -H -p <PID> # 查看進程內所有線程的CPU使用率
-
Node.js:
const { threadId } = require('worker_threads'); console.log(`Worker ${threadId} 正在運行`);
2. 并行計算驗證
-
示例:計算 π 的近似值(蒙特卡洛方法)
// main.js const { Worker } = require('worker_threads'); const numWorkers = 4; const totalSamples = 1e8;const workers = Array.from({ length: numWorkers }, (_, i) => {const worker = new Worker('./piWorker.js');worker.postMessage({ samples: totalSamples / numWorkers });return worker; });let results = []; workers.forEach((worker, i) => {worker.on('message', (result) => {results[i] = result;if (results.length === numWorkers) {const pi = results.reduce((sum, val) => sum + val) / numWorkers;console.log(`π ≈ ${pi}`);}}); });
// piWorker.js const { parentPort } = require('worker_threads');parentPort.on('message', ({ samples }) => {let inside = 0;for (let i = 0; i < samples; i++) {const x = Math.random();const y = Math.random();if (x * x + y * y <= 1) inside++;}parentPort.postMessage(4 * inside / samples); });
六、總結
-
worker_threads
是并行計算:- 利用多核 CPU,通過操作系統級線程實現任務并行執行。
- 適用于 CPU 密集型任務,避免阻塞主線程的事件循環。
-
與主線程的并發模型互補:
- 主線程處理 I/O 和事件驅動的并發。
- Worker 線程處理 CPU 密集型任務的并行計算。
通過合理使用 worker_threads
,您可以充分發揮多核 CPU 的性能優勢,構建高效、響應迅速的 Node.js 應用。