A thread of execution is the smallest sequence of programmed instructions that can be managed independently by a scheduler, which is typically a part of the operating system. Understand the following way:
Imagine you have to bake some cakes. In the first case, you have a single oven for baking. When an order comes for a cake, you put the batter in the oven and set the timer. When the timer reaches zero you take out the cake and serve it. Now imagine that another order comes while the first cake is still cooking, well obviously you will have to wait till the first one is finished baking before you bake the second one.
This example is similar to a single threaded architecture. A single thread can execute only a single task at any instant of time. If another process need to execute, it has to wait till the thread becomes free.
Now suppose you have 10 ovens. In this case you can bake upto 10 cakes at a time. At it is probable that all 10 of them are not used at the same time. This is how multi-threaded architecture works.
That is about threads. But what is NodeJS? Single threaded or multithreaded?
Again go to bakery. Whenever a customer comes, does he put the cake in the over? No! right?... A customer gives his/her order to you who then looks for free ovens and starts baking. This is the model followed by NodeJS.
NodeJS has a main process which is responsible for communicating with the clients, taking instructions from the customers, uses any free threads from its internal thread pool, fetches result from threads and send the result back to the customer.
Now let a customer enter your bakery and give some task to you which would take you around 5 minutes to complete. During these 5 minutes, since you are busy executing some task you won’t be able to handle other customers or assign new processes. This would cause a delay for the customer who may leave after frustration.
Similarly if you keep the NodeJS’ main thread busy, it will cause delay in responding to the clients. This is a bad design as any server should try to minimise the response delay. Hence it is a good practice to execute long time consuming tasks in child threads.
See the working of threads in the following example.
Hello World Application
In this example, we will display the contents of a file to console. For this we will be using ‘fs’ module of NodeJS which enables us to perform file I/O.
Create a new project and create a new file server.js and myTextFile.txt with the following content:
Hello..!! I am inside myTextFile.txt
Here the ‘path’ module is used for specifying the address of the text file independent of the operating system.
As expected.No surprised here.
Now let us read the file in another thread.
Modify the sayHello() function above as
Unexpected??????? You might be wondering why the second console.log() is executed first. Well that is where threads come into play.
The code you run is always on the main thread. So when you call sayHello() function, you are calling it in the main thread. Now in the sayHello() function, the first statement is executed as readFile BUT this function is executed in a separate thread. This fs.readFile() handles reading file in a separate thread. The logic is defined in the core NodeJS modules. You pass a callback function as an argument to readFile() function which is executed after the reading of file is complete.
fs.readFile() executes in another thread as said above BUT the outer console.log() executes in the main thread. That is why it executes while the other thread is processing.
In the next article we will show how to create another thread manually.