Stepping into the world of Threads

malindu ruwantha
5 min readJul 13, 2021

Part 1

Why we need them

Before stepping into the world of threads, Let's have an idea about where we might need them. Think of a situation where you build the Order processing module of an enterprise application.

The underlying process would be as follows

1.User Creating and Submitting the order
2.Validation of the fields
3.Persistence of the data in the database
4.changing the status of the order (New Order -->> Submitted Order)
5.Extracting data for the reporting tables
6.calculation of the net values and net prices

Imagine you run this application in a single-threaded environment. user waits until all these processes to happen one after another to get the feedback in the UI. It's not efficient, isn't it?
but what if we can show the user that the order is submitted while doing the other transactional processes in the background. Sounds good, isn't it?
That's where multithreading comes in handy. It can be utilized to run several processes parallelly.

Mainly once we launch a Java Application, the main thread is the one that executes. Originated with the main() method in the main stack. If we start another thread of execution, A new stack will be instantiated.

Execution of Threads

Although JVM can start a couple of threads at the same time, it's not guaranteed to run all the threads at the same moment. The number of threads that can be run in parallel is depending on the CPU and is controlled by the thread Scheduler. If the CPU can run only two threads at the same time and there are four runnable threads, the thread scheduler will choose two among them. Others will have to wait. What I wanted to highlight is we don't have control over the execution of threads.

Creating a Thread

There are two ways of define and instantiating a thread.
1.Extending Thread Class
2.Implementing Runnable Interface

There is no much difference as the Thread class itself is implementing the Runnable interface. The difference lies in the way of starting the thread.

Extending the Thread Class

In Java, only one class can be extended. So it is always good to use threads by implementing the Runnable Interface.

Declare Threads using Runnable

Although we used the Runnable interface it is mandatory to instantiate a Thread .start() can only be called for an instance of a Thread.

Using lambda to implement Runnable

Java.Lang.Runnable is a Functional interface so that lambda expressions can be used to implement it.

After the creation of the Thread instance as

t1 instance of Thread is in NEW state until the start() method is called. After start() is called upon the thread instance, it moves from the NEW state to Runnable state. Now the Thread can be chosen by the scheduler .whenever the thread is chosen its run() method will be executed. After finishing the execution of the run() method Thread is considered dead and the call stack will be terminated.

The Thread States and Transitions

Sleeping an Executing Thread

Thread execution can be halted without sending it to the Runnable pool using the sleep () method. It's a static method of the class Thread. sleep() may throw a checked exception as InteruptedException and need to handle or declare.

following is a code block for an instance using the sleep()

parameters for the sleep method are passed as milliseconds. So according to the above example Thread. sleep() will stop the thread execution and after 1000 mile seconds thread will be sent back to the runnable pool. Then the thread scheduler can pick up the thread to continue the execution.

Thread Priorities

All the Threads instances have apriority denoted by an integer value from 1–10. The default priority value for the thread is 5 and one can set the priority of a thread explicitly as follows.

the output of the above application is as follows

So whenever there is a thread in the runnable pool with a high priority than the currently executing thread, Scheduler will switch the execution to the high priority thread. If the priority levels are the same execution will be handled normally.

The yield() method will send a running thread to the runnable state, allowing the scheduler to choose another thread with the same priority. but it's not guaranteed the execution of a separate thread. scheduler might choose the same thread again for the execution. yield() is also a static method from class Thread.

Join() method

we have identified two static methods from the Thread class. now let's move on to a non-static method join().this can be used to join a thread to another.

As an Example Lets take two threads

Thread t1 = new Thread();

t1.start()

once we execute t1.start() Thread will start its execution.half away through lets initiate another thread as,

Thread t2= new Thread();
Keep in mind at this moment t1 is still executing and we will name it as a currently running thread.

Then we call the start() for t2 and join().

t2.start();

t2.join()

Currently, the running thread will stop its execution and it joins itself to the end of t2. That means t1 will resume its execution once the t2 finishes its execution.

From the next story, let's go through Synchronization and some general problems related to threads.

--

--