Node.js is multithreaded, but the main thread, just like any multithreaded programming language, will operate by defaults. To multithread a node.js application and run multiple parallel threads, which can handle different tasks separately and simultaneously, you will have to implement the worker_thread and assign this your above task to a single worker_thread to handle, independent of the main thread. you need to do the following.
- Confirm that you have a multiple core processor, you can do that by invoking the available parallism or the cpus methods of the "os" native node package, or using the
nproc command on linux or checking the windows task manager performance and look for the logical processors.
const os = require("node:os");
let THREAD_COUNT;
//THREAD_COUNT = os.cpus().length;
//or this
THREAD_COUNT = os.availableParallelism();
- implement a worker thread in a separate JS file, you can add this your counter task there, to execute as a separate thread, uninterrupted and non-blocking, by using the
workData and parentPort properties of the worker_threads native node.js package.
const { workerData, parentPort } = require("worker_threads");
In node.js the main thread and the worker threads can communicate either one way communication or duplex communication using these properties of the worker_thread package.
The workerData contain the data you can pass to the worker thread from the main thread, while the parentPort contain a method called postMessage you can use to communicated back to the main thread.
- Implement a "worker" class, that will run as a an independent JS execution thread, totally different from the main thread. this class is also a component of the
worker_thread native package.
const { Worker } = require("worker_threads");
Instantiate a new Worker class and pass the worker thread you have just created earlier, like so.
const worker = new Worker("path to the worker thread", {
workerData: { data: "data to the worker thread" },
});
Pass the path to the worker thread to the new Worker class and also pass data to the worker_thread if you will.
It's recommended that you wrap this Worker class in a new promise, to insure when the worker threads completes, especially if you intend to communicate between the worker thread and the main thread.
The communication is event driven, which works like node.js native event implementation, but without Emitter class instantiation, because the Worker class has it's own even implementation by default, to enable this duplex communication between the main thread and the worker threads, like so.
worker.on("message", (data) => {
});
worker.on("error", (msg) => {
});
For both message and error event registers, on the Worker class, to pass message or error from the worker threads.
If you have wrapped the Worker class in a new promise, you can use resolve and reject functions of the promise to handle each case respectively.
With is setup, you have successfully implemented a multithread node.js application in a non-blocking fashion and you can send different task to the main thread or the worker threads.
You will know that you have done this properly when you keep the main JS thread busy with a huge CPU task, like say loop a 1_000_000_000 times, which is usually blocking in a normal JS single threaded application, executed by the main thread, then send a request to the worker_thread when the main thread is busy, you will get a response or task execution result, if you have implemented it like I have just done.