Before we dive deep into Multithreading in Java. Let’s say we want our program to execute multiple processes. How do we do it?

Basically, there are two ways to achieve multi-tasking:

  1. Multi-threading
  2. multi-processing

However, we use multithreading than multiprocessing because threads use a shared memory area. They don’t allocate separate memory areas so it saves memory. Moreover, context-switching between the threads takes less time than process.

Advantages of Java Multithreading

  • It doesn’t block the user because threads are independent and you can perform multiple operations at the same time.
  • You can perform many operations together, so it saves time.
  • Threads are independent, so it doesn’t affect other threads if an exception occurs in a single thread.

multithreading in java

What are Threads in Java?

A thread is a lightweight subprocess. It is a separate path of execution.
Threads are independent. It uses a shared memory area. Java provides the Thread class to achieve thread programming. Thread class provides constructors and methods to create and perform operations on a thread. The Thread class extends the Object class and implements the Runnable interface.

How to use Threads in Java?

There are two ways to use threads in Java. Let’s look at them one at a time.

1.By extending the Thread class

In this method, we extend the features of the already defined Thread class using the extends key-word. Then we override the method named run(), which is going to be executed when the thread starts.
Finally, in the main method, we start the thread using the start() method.

class Demo extends Thread{  
public void run(){  
System.out.println("thread is running...");  
}  
public static void main(String args[]){  
Demo thread=new Demo();  
thread.start();  
 }  
} 

OUTPUT

thread is running...

2.By Implementing the Runnable Interface

Here, we implement the runnable interface in the Demo class. Then create an Object of it and pass it as an argument to the Object of Thread class.

class Demo implements Runnable{  
public void run(){  
System.out.println("thread is running...");  
}  
  
public static void main(String args[]){  
Demo run=new Demo();  
Thread t1 =new Thread(run);  
t1.start();  
 }  
}

OUTPUT

thread is running...

Thread Scheduler in Java Multithreading

Thread scheduler in java is the part of the JVM that decides which thread should run. There is no guarantee that which runnable thread will be chosen to run by the thread scheduler. Only one thread at a time can run in a single process.

Thread Priority

Each thread has a priority. Priorities are represented by a number between 1 and 10. In most cases, thread schedular schedules the threads according to their priority (known as preemptive scheduling). But it is not guaranteed because it depends on the JVM specification that which scheduling it chooses.

The join() method

The join() method causes the currently running threads to stop executing until the thread it joins with completes its task.

class Demo extends Thread{  
	public void run(){  
		for(int i=1;i<=5;i++){  
			try{  
				Thread.sleep(500);  
			}catch(Exception e){System.out.println(e);}  
			System.out.print(i+" ");  
		}  
	}  
	public static void main(String args[]){  
		Demo t1=new Demo();  
		Demo t2=new Demo(); 
		Demo t3=new Demo(); 
		t1.start();  
		try{  
			t1.join();  
		}catch(Exception e){System.out.println(e);}  

		t2.start();  
		t3.start();  
	}  
}  

OUTPUT

1 2 3 4 5 1 1 2 2 3 3 4 4 5 5

Naming Thread in Java Multithreading

The Thread class provides methods to change and get the name of a thread. By default, each thread has a name i.e. thread-0, thread-1, and so on. By we can change the name of the thread by using the setName() method. The syntax of setName() and getName() methods are given below:

public String getName(): is used to return the name of a thread.
thread.setName("my-thread-name");
public void setName(String name): is used to change the name of a thread.
thread.getName();
//returns a string containing thread name

Example of naming a thread

class Demo extends Thread{  
	public void run(){  
		System.out.println("running...");  
	}  
	public static void main(String args[]){  
		Demo t1=new Demo();   
		System.out.println("Name of t1: "+t1.getName());  

		t1.setName("my-thread");  
		System.out.println("After changing name of t1: "+t1.getName());  
	}  
} 

OUTPUT

Name of t1: Thread-0
After changing name of t1: my-thread

Advantages of Thread over Process

  1. Responsiveness: Threads are independent. This means, if one thread completes its execution, then its output can be immediately returned.
  2. Faster context switch: Context switch time between threads is lower compared to process context switch.
  3. Effective utilization of multiprocessor system: If we have multiple threads in a single process, then we can schedule multiple threads on multiple processors. This will make process execution faster.
  4. Resource sharing: Resources like code, data, and files can be shared among all threads within a process.
    Note: stack and registers can’t be shared among the threads. Each thread has its own stack and registers.
  5. Communication: Communication between multiple threads is easier, as the threads share a common address space. while in the process we have to follow some specific communication techniques for communication between two processes.

Thread Life Cycle in Java

A thread once created goes through certain life stages in a program. There are mainly five stages:

  • New
  • Runnable
  • Running
  • Non-Runnable (Blocked)
  • Terminated

Java Thread life cycle