Node.js có phải là single-thread?
Câu trả lời là: Có và Không.
- Có – vì event loop của Node.js chạy trên một thread duy nhất.
- Không – vì Node.js ngầm sử dụng nhiều thread phía sau thông qua thư viện
libuv
.
Nói cách khác: JavaScript trong Node chạy trên 1 thread, nhưng Node có thể tận dụng đa luồng cho một số tác vụ nặng như I/O, xử lý file, crypto...
Các cách sử dụng đa luồng trong Node.js
1. Worker Threads (Từ Node v10.5 trở lên)
worker_threads
cho phép bạn tạo thêm các thread độc lập trong JS để xử lý các tác vụ tính toán nặng.
// main.js
const { Worker } = require('worker_threads'); new Worker('./heavy-task.js');
// heavy-task.js
console.log('Heavy task running in a separate thread!');
Thích hợp cho CPU-bound task như tính toán, xử lý ảnh, mã hóa.
2. Cluster module – scale theo CPU core
Module cluster
giúp bạn fork nhiều process Node.js để tận dụng đa nhân CPU. Mỗi process là một instance độc lập.
const cluster = require('cluster');
const http = require('http');
const os = require('os'); if (cluster.isMaster) { const cpuCount = os.cpus().length; for (let i = 0; i < cpuCount; i++) { cluster.fork(); }
} else { http.createServer((req, res) => { res.end('Handled by worker ' + process.pid); }).listen(3000);
}
Dùng để tăng throughput của server HTTP hoặc WebSocket.
3. libuv thread pool (ẩn)
Một số API như fs
, crypto
,dns.lookup()
... thật ra không chạy trong event loop, mà chạy trong thread pool do libuv cung cấp.
Ví dụ:
const crypto = require('crypto'); console.time('hash');
crypto.pbkdf2('password', 'salt', 100000, 64, 'sha512', () => { console.timeEnd('hash');
});
Bạn có thể thay đổi số thread trong pool:
process.env.UV_THREADPOOL_SIZE = 8;
Khi nào nên dùng multi-thread?
- Khi có tác vụ tính toán nặng và blocking (CPU-bound)
- Khi muốn tăng hiệu suất server bằng cluster
- Khi muốn tận dụng đa nhân CPU Còn lại, hãy tận dụng event loop và non-blocking I/O – đó mới là sức mạnh gốc của Node.js.
Kết luận
Mặc dù JavaScript trong Node là single-thread, nhưng Node.js không hề đơn giản như bạn tưởng. Nó có thể tận dụng đa luồng cực kỳ linh hoạt với:
- Worker Threads cho CPU-bound task
- Cluster để scale server
- Thread pool của libuv cho một số API
Nếu biết cách dùng hợp lý, bạn có thể “vắt kiệt hiệu năng” từ Node.js mà không cần chuyển sang ngôn ngữ khác.