跳至主要内容

Node.js Process 與 Worker Threads

📌 1. 基本概念

Node.js 在 JavaScript 執行層面為單執行緒,但底層(如 I/O 操作、libuv thread pool)是多執行緒。這讓 Node.js 能同時處理大量 I/O 任務,並可透過 child_process 或 worker_threads 實現平行運算。

📌 2. process 與 child_process 模組

✅ process 物件(全域物件)

提供與當前執行流程互動的 API。

屬性 / 方法說明
process.pid目前行程 ID
process.argv執行參數
process.env環境變數
process.exit()結束程序
process.on('exit')程式結束前的 callback
process.on('uncaughtException')捕捉未處理例外

✅ child_process 模組

允許在 Node.js 中建立子行程(process),達到真正平行處理。

三種用法:

const { exec, spawn, fork } = require('child_process');

// exec:執行 shell 指令
exec('ls -la', (err, stdout) => console.log(stdout));

// spawn:啟動子行程並與 stdin/stdout 溝通
const ls = spawn('ls', ['-lh']);
ls.stdout.on('data', data => console.log(`輸出: ${data}`));

// fork:啟動 Node.js 子行程(可互傳訊息)
const child = fork('worker.js');
child.send({ hello: 'world' });

📌 3. Worker Threads 模組

從 Node.js v10.5 開始引入,v12 以上穩定。適合處理 CPU 密集運算(非 I/O)。

// worker.js
const { parentPort } = require('worker_threads');
parentPort.postMessage('Hello from worker');

// main.js
const { Worker } = require('worker_threads');
const worker = new Worker('./worker.js');
worker.on('message', msg => console.log(msg));

📌 4. child_process vs worker_threads

項目child_processworker_threads
執行單位獨立行程同行程內的執行緒
記憶體隔離有(各自空間)無(可共享記憶體)
IPC 通訊send, on('message')postMessage, on('message')
適用場景子系統執行 / shellCPU 密集任務
效能較高開銷較低開銷,效能佳

📌 5. 常見面試題與解析

🧠 Q1:Node.js 是單執行緒嗎?那怎麼處理高併發?

✅ 建議答法:

雖然 Node.js 在 JavaScript 層面是單執行緒,但透過非阻塞 I/O 模型與 libuv 的 thread pool,可同時處理大量 I/O 任務。而 CPU 密集型任務則可用 worker_threads 或 child_process 平行處理。


🧠 Q2:spawn, exec, fork 差異是什麼?

方法適合場景備註
exec簡單 shell 指令回傳整體 output
spawn大量資料流資料流(stream)方式處理
forkNode 子程式可傳遞 JS 物件,最適 Node 專案內模組溝通

🧠 Q3:在什麼情況下該使用 worker_threads?

✅ 建議答法:

當需要進行大量 CPU 密集處理(如影像處理、壓縮、加密)時,使用 worker threads 可平行執行任務而不阻塞主執行緒。


🧠 Q4:如何在多執行緒間共享資料?

worker_threads 可使用 SharedArrayBuffer 與 Atomics。

child_process 間則無法共用記憶體,只能靠訊息傳遞。

📘 延伸學習資源