Node.js worker_threads Module
Node.js'sworker_threadsmodule allows developers to create multiple threads in Node.js applications. Unlike the traditional single-threaded Node.js model, this module lets you execute JavaScript code in separate threads, enabling true parallel processing.
Why Multi-threading is Needed
Node.js is single-threaded by default, which means:
- CPU-intensive tasks will block the event loop
- Unable to fully utilize the performance of multi-core CPUs
- Long-running computations will reduce the responsiveness of the application
worker_threadsThe module solves these problems, allowing you to offload CPU-intensive tasks to other threads.
Basic Concepts
Main Thread vs Worker Thread
- Main thread: The main execution thread of the application, responsible for creating and managing worker threads.
- Worker thread: An independent execution thread created by the main thread, used to execute specific tasks.
Inter-thread Communication
Worker threads and the main thread communicate via message passing rather than shared memory. This approach avoids complex synchronization issues.
Core API
Main Components of the worker_threads Module
Example
Worker, // Class used to create new threads
isMainThread, // Determine whether the current context is the main thread
parentPort, // Used to communicate with the parent thread
workerData // Data passed when the thread is created
} = require('worker_threads');
Usage Example
Create a Simple Worker Thread
Main thread code (main.js):
Example
if (isMainThread) {
// Main thread code
console.log('This is the main thread');
// Create a worker thread
const worker = new Worker('./worker.js', {
workerData: {
message: 'Hello, worker thread!'
}
});
// Listen for messages from the worker thread
worker.on('message', (msg) => {
console.log(`Received from worker thread: ${msg}`);
});
worker.on('error', (err) => {
console.error('Worker thread error:', err);
});
worker.on('exit', (code) => {
if (code !== 0) {
console.error(`Worker thread exited unexpectedly, exit code: ${code}`);
}
});
} else {
// Worker thread code
require('./worker.js');
}
Worker thread code (worker.js):
Example
console.log('This is the worker thread');
console.log('Received message from main thread:', workerData.message);
// Simulate some work
setTimeout(() => {
// Send a message to the main thread
parentPort.postMessage('Work complete!');
}, 2000);
Advanced Usage
Passing Complex Data
Example
const worker = new Worker('./worker.js', {
workerData: {
array: new Uint8Array([1, 2, 3, 4]),
object: { key: 'value' }
}
});
// Worker thread
console.log(workerData.array); // Uint8Array [ 1, 2, 3, 4 ]
console.log(workerData.object); // { key: 'value' }
Shared Memory (SharedArrayBuffer)
Example
const sharedBuffer = new SharedArrayBuffer(16);
const arr = new Uint8Array(sharedBuffer);
arr[0] = 1;
const worker = new Worker('./worker.js', {
workerData: { sharedBuffer }
});
// Worker thread
const { sharedBuffer } = workerData;
const arr = new Uint8Array(sharedBuffer);
console.log(arr[0]); // 1
Best Practices
- Reasonable usage: Don't create a thread for every small task; creating threads has overhead.
- Error handling: Always listen for the 'error' and 'exit' events of worker threads.
- Resource cleanup: Ensure worker threads exit properly after completing their tasks.
- Communication optimization: Minimize the amount of data passed in inter-thread communication.
- CPU affinity: For long-running threads, consider setting CPU affinity.
Performance Considerations
- Thread pool: For frequent short-term tasks, consider using a thread pool pattern.
- Load balancing: Distribute worker threads evenly across multi-core systems.
- Memory usage: Each worker thread has its own V8 instance and memory space.
Common Questions
When should you use worker_threads?
- CPU-intensive computations
- Need to process multiple tasks in parallel
- Need to utilize multi-core CPUs
What is the difference between worker_threads and the cluster module?
clusterCreates multiple Node.js processesworker_threadsCreates threads that share the same process
How to debug worker threads?
Use--inspectand--inspect-brkflag, and assign a different debugging port to each worker thread.
Example
Summary
Node.js'sworker_threadsmodule brings true multi-threading capabilities to JavaScript, allowing developers to better utilize the performance of modern multi-core CPUs. By using worker threads appropriately, you can significantly improve the performance of CPU-intensive applications while maintaining Node.js's non-blocking I/O advantages.
Node.js Built-in Modules