skip to content
Profile image
Dharmendra Kashaudhan
Multithreading

Multithreading in Node.js using worker thread

/ 4 min read

In the realm of server-side JavaScript, Node.js has become a dominant force due to its event-driven, non-blocking I/O model, which allows for highly scalable and efficient server-side applications.

Node.js has traditionally been single-threaded, meaning it operates within a single process and can only leverage a single CPU core. This limitation has prompted the development of various strategies to achieve parallelism and concurrency, one of which is through multithreading. In this article, we’ll explore the concept of multithreading in Node.js, its benefits, and how it can be implemented using native modules and worker threads.

Understanding Multithreading

Multithreading refers to the ability of an application to execute multiple threads concurrently, allowing for parallel execution of tasks.

Node.js executes JavaScript code within the Event Loop, which handles both initialization tasks and callbacks. It also manages non-blocking asynchronous operations such as network I/O. It executes in the same thread as the JavaScript code itself. When a JavaScript operation blocks the thread, the event loop is also blocked.

To avoid main thread blocking we can use Worker Pool thread. It spawns a new thread manages a separate thread which synchronously executes the task & return the result to the event loop. Then the provided callback is executed by the event loop with the returned result.

Worker Pool threads in Node.js are tasked with handling operations that cannot be executed asynchronously at the operating system level, along with certain CPU-intensive APIs. These threads are responsible for offloading such work, ensuring smooth operation and efficient resource utilization.

Developers have no control over the Worker Pool threads which are managed by the Node.js itself.

Why multithreading?

  1. Improved Performance: By utilizing multiple CPU cores, multithreading allows Node.js applications to handle more requests concurrently, leading to improved performance and reduced response times.

  2. Scalability: Multithreading enables horizontal scaling by distributing workload across multiple threads, allowing applications to handle a larger number of concurrent users and requests.

  3. Resource Utilization: With multithreading, CPU-bound tasks can be offloaded to separate threads, preventing them from blocking the main event loop and improving overall responsiveness.

  4. Enhanced Responsiveness: By executing tasks concurrently, multithreading prevents long-running operations from blocking the main thread, ensuring that the application remains responsive to incoming requests.

Implementing Multithreading in Node.js

Worker thread

Node.js introduced the worker_threads module to provide a high-level API for creating and communicating with worker threads.

Unlike native addons, worker threads are implemented entirely in JavaScript and offer a more accessible and safer approach to multithreading.

Here’s how you can use worker threads to perform parallel processing:

main.js
const { Worker } = require('worker_threads');
const workers = [];
for (let i = 0; i < 4; i++) {
const worker = new Worker('./worker.js');
workers.push(worker);
}
workers.forEach((worker) => {
worker.once('message', (message) => {
console.log(message); //
});
});
workers.forEach((worker) => {
worker.postMessage('Hello from the main thread!'); // send message to worker thread
});

worker.js
const { parentPort } = require('worker_threads');
parentPort.once('message', (message) => {
console.log(message);
// some CPU intensive task
parentPort.postMessage('Hello from the worker thread!'); // sends message back to main thread
});

In the above code, we create a separate JavaScript file (worker.js) that defines a worker thread. The worker thread listens for messages from the main thread which is created in (main.js) when and spawns 4 worker threads. The main thread sends message once to the worker thread, upon receiving message the worker thread starts executing the CPU intensive task. Once the task is completed, the worker thread sends a message back to the main thread.

Cover

Conclusion

Multithreading offers a powerful mechanism for achieving parallelism and concurrency in Node.js applications, enabling them to fully utilize the available hardware resources and improve performance. Whether through native addons or worker threads, Node.js provides several approaches for implementing multithreading, each with its own advantages and use cases.

By harnessing the power of multithreading, developers can build highly scalable and responsive applications capable of handling a large number of concurrent requests.