Multithreading in Java

The mechanism of executing multiple threads simultaneously is known as multithreading. A thread is a sequence of method calls within the program. Every thread is independent and has its program counter, stack and local variable. In this tutorial, I am going to cover all the concepts that are related to threads. We will cover what are threads, Why do we need multithreading, how can we create threads, what is the concept of threads, examples of multithreading in java.

What are the threads?

A Thread is a lightweight process. They allow multiple tasks to be performed at the same time. All the threads share the same address space. Since they share the same address they can have common data and code.

What is the difference between threads and process?

1.     A Thread is a part of a process whereas a process is defined as a program in execution.

2.     Each thread has its stack. Multiple threads share the same address space of process whereas process has its address space.

3.     Threads are lightweight whereas processes are heavyweight

4.     As threads are lightweight they have less overhead as compared to the process.

5.     For communication process uses Interprocess communication whereas threads can communicate directly as they share the same address.

The life cycle of a thread

A thread goes through different stages during its life cycle. The below diagram shows different stages of the cycle.


Let us discuss these:

1.     New - this stage is also referred to as a born stage. This is the initial stage wherein a thread is created and will remain in this thread until the program starts it.

2.     Runnable - This stage comes when a thread starts its execution. This stage comes when we call start().

3.     Running - this stage comes when the thread scheduler selects the thread. run() invokes this stage.

4.     Waiting - from the running stage while the thread is running if we can sleep() or wait() methods then this stage comes into the picture.

5.     Dead - this stage comes when the thread execution is completed. This stage is also known as the terminated stage.

Thread priorities

To make the multiple threads run in order the OS scheduler needs to divide the multiple threads based on thread priority. Hence, to achieve this each thread is assigned with its priority.

The range of priority is defined by three variables i.e. MIN_PRIORITY, a constant of 1, MAX_PRIORITY, a constant of 10 and NORM_PRIORITY, a constant of 5. By default, NORM_PRIORITY is declared for every thread.

The threads which have higher priority will be scheduled first as compared to lower priority threads. However, the priority of a thread is not the sole reason for thread execution, the operating system also plays a very big role.

How to create a thread in java

There are mainly two ways by which we can create a thread.

1.     Implementing the runnable interface

2.     Extending the thread class

There is a significant difference in when to use which method. Consider the scenario in which the class is already extending another class and as java does not support multiple inheritance hence we will not be allowed to create a thread by extending the class. Hence, in cases when the class is extending another class, we can create a thread by implementing the runnable interface.

Also, if we know that the class implementation is full and in future also we will not be extending this class with another class then we can create the thread by extending the thread class otherwise, we should implement the runnable interface.

Let’s discuss both these ways in detail with an example:

Creating thread by Implementing a runnable interface

Steps need to be followed to create a thread using the runnable interface.

1.     The runnable interface has run() method which we need to implement into the class. This will create an entry point for the thread. All the main logic which requires threading will be under this method.

2.     In the second step, we need to create the object of the thread class using its default constructor

                        Thread(Runnable Obj, String threadName)

            The obj should be the instance of the class which implements the runnable interface.

  1. As the last step, after the thread object is created, we need to call start() method on the object of the runnable class. This will internally call the run() method.

Below is the example of creating and running a thread.

Output:

Creating Stage Thread t1

Starting stage Thread t1

Creating Stage Thread t2

Starting stage Thread t2

Running Stage Thread t1

Thread:  Thread t1, 4

Running Stage Thread t2

Thread:  Thread t2, 4

Thread:  Thread t1, 3

Thread:  Thread t2, 3

Thread:  Thread t1, 2

Thread:  Thread t2, 2

Thread:  Thread t1, 1

Thread:  Thread t2, 1

Thread t1 exiting

Thread t2 exiting

 

Creating a thread by extending thread class

Steps need to be followed to create a thread by extending thread class

1.     Thread class has an abstract run() method which we need to override into the class. This will create an entry point for the thread. All the main logic which requires threading will be under this method.

2.     As the last step, after the thread object is created, we need to call start() method on the object of the runnable class. This will internally call the run() method.

Below is the example of creating and running a thread.

Output:

Creating Stage Thread t1

Starting stage Thread t1

Creating Stage Thread t2

Starting stage Thread t2

Running Stage Thread t1

Thread:  Thread t1, 4

Running Stage Thread t2

Thread:  Thread t2, 4

Thread:  Thread t1, 3

Thread:  Thread t2, 3

Thread:  Thread t1, 2

Thread:  Thread t2, 2

Thread:  Thread t1, 1

Thread:  Thread t2, 1

Thread Thread t1 exiting

Thread Thread t2 exiting

Important Thread methods

 

Sr. No.

Methods and Description

1.

public void start()

2.

public void run()

3. 

public final void setName(String name)

4.

public final void setPriority(int priority)

5.

public final void setDeamon(boolean on)

6.

public final void join(long milisec

7.

public void interrupt()

8.

public final boolean isAlive()

9.

public static void yield()

10.

public static void sleep(long milisec)

11.

public static boolean holdsLock(Object x)

12.

public static Thread currentThread()

13.

public static void dumpStack()


Inter-thread Communication

Threads concept in java provides a very seamless way so that threads can communicate with each other. There can be scenarios where multiple threads want to share some information. In this case, we need inter-thread communication.

Inter-thread communication is also important to overcome Deadlock. Deadlock is the case when multiple threads are waiting for the object access.

There are three methods which facilitate inter-thread communication:

Sr. No.

Methods and Description 

1.

public void wait()

2.

public void notify()

3.

public void notifyAll()


public void wait()
 - takes the thread to wait for the state until notify() called.

public void notify() - wakes the thread on which wait() was called.

public void notifyAll() - wakes all the threads on which wait() was called.

All these methods are in object class as they deal with objects and perform the operations on objects. Hence, they are available in all the classes. Only synchronized context can call these methods.

Let’s go through an example where two threads communicate with each other using wait() and notify().

Conclusion:

As we have seen the importance of thread in java programming. Java threads come handy when we have a multi-threaded environment. Helps to run the multiple processes at the background.

Please feel free to add some points and also correct me if I am wrong at any point.

 


Post a Comment

0 Comments