Code360 powered by Coding Ninjas X Naukri.com. Code360 powered by Coding Ninjas X Naukri.com
Table of contents
1.
Introduction
2.
What is Multithreading in Java?
2.1.
Extending the Thread class
2.2.
Java
2.3.
Implementing the Runnable Interface
2.4.
Java
3.
Advantages of Java Multithreading
4.
Limitations of Java Multithreading
5.
Life Cycle of a Thread
6.
What is Thread in java?
7.
Java Thread class
8.
Java Thread Methods
8.1.
Example
9.
Thread Creation
9.1.
What is Thread Class?
9.2.
What is a Runnable Interface?
10.
Thread priority
10.1.
Thread Scheduling
10.2.
Thread Synchronization
11.
Frequently Asked Questions
11.1.
What is the multithreading in Java?
11.2.
What is multithreading with example?
11.3.
What are the two types of multithreading?
11.4.
What are two advantages of multithreading?
12.
Conclusion
Last Updated: Mar 27, 2024
Medium

Multithreading in Java

Author Yashesvinee V
1 upvote
Crack Google SDE interview : Essential projects
Speaker
Saurav Prateek
SDE-2 @
20 Jun, 2024 @ 01:30 PM

Introduction

Multithreading in Java is a process of executing two or more threads simultaneously. Java multithreading runs multiple applications and allocates processing power to them.

multithreading in java

In this article, we will discuss multithreading in Java. We will discuss how to create multiple threads. Multithreading is an important feature in Java. It allows programs to take full advantage of modern multi-core processors and perform multiple tasks concurrently. Let us understand more about multithreading in Java. 

Also see,  Swap Function in Java

What is Multithreading in Java?

The primary programming interface in multithreaded programming is the thread. Threads are visible only from within a process. They share resources like address and memory space, files, etc. Concurrency is a condition that exists when at least two threads are making progress and Parallelism is a condition that arises when at least two threads execute simultaneously.

Multithreading extends the concept of multitasking, where operations within an application are divided into individual threads. Threads in Java can be created either by extending the Thread class or by implementing the Runnable interface.

There are two mechanisms where threads can be created:

  • Extending the Thread class
  • Implementing the Runnable Interface

Extending the Thread class

Extending the Thread class in Java allows you to create your own custom thread by inheriting from the Thread class. This approach is used for multi-threading, where multiple threads run concurrently to perform different tasks within a program. By extending the Thread class, you have the advantage of customizing the behavior of the thread by overriding the run method. However, this approach has limitations since Java supports single inheritance. If you extend Thread, your class cannot extend any other class.

Here's an example using the Runnable interface:

  • Java

Java

public class CustomRunnable implements Runnable {
@Override
public void run() {
// Code to be executed by the custom thread
}
}

public class Main {
public static void main(String[] args) {
CustomRunnable customRunnable = new CustomRunnable();
Thread thread = new Thread(customRunnable);
thread.start();
}
}

Implementing the Runnable Interface

Implementing the Runnable interface in Java involves creating a class that implements the Runnable interface and overriding its run method. This approach is used for creating threads and is preferred over extending the Thread class because it allows better flexibility in class design and avoids the limitations of single inheritance. By implementing the Runnable interface, you separate the task to be performed by the thread from the threading mechanism itself. This makes your code more modular and flexible.

Let's say you want to create a simple program that prints numbers from 1 to 10 using a separate thread. Here's how you could implement it using the Runnable interface:

  • Java

Java

public class NumberPrinter implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
System.out.println(i);
}
}
}

public class Main {
public static void main(String[] args) {
NumberPrinter numberPrinter = new NumberPrinter();
Thread thread = new Thread(numberPrinter);
thread.start(); // Start the thread to print numbers concurrently
}
}

 

In this example, the NumberPrinter class implements the Runnable interface and defines the task to print numbers. The Main class creates an instance of NumberPrinter and starts a new thread to execute the task. This allows the numbers to be printed concurrently with the main thread.

Get the tech career you deserve, faster!
Connect with our expert counsellors to understand how to hack your way to success
User rating 4.7/5
1:1 doubt support
95% placement record
Akash Pal
Senior Software Engineer
326% Hike After Job Bootcamp
Himanshu Gusain
Programmer Analyst
32 LPA After Job Bootcamp
After Job
Bootcamp

Advantages of Java Multithreading

  • It improves concurrency and application responsiveness. Since each activity is defined as a thread, there is no need to wait for one thread to complete to start another. 
     
  • It improves program structure. Programs are written in multiple independent or semi-independent units of execution instead of a single piece of code. 
     
  • Reduced utilization of resources and decreased cost of maintenance. Multiple threads share the same address and memory space or files simultaneously, so the requirement for additional resources is reduced.

Limitations of Java Multithreading

  • Writing code for multithreaded applications is challenging. Their results cannot be easily predicted.
     
  • Complex debugging and testing. Finding the root cause of an error and debugging it becomes complex and difficult compared to single-threaded programs. Defects related to time-slicing are often tricky to discover and test.
     
  • Inefficient management of Concurrency and Parallelism may cause problems in the application.
     

See Threads For Concurrency.

Life Cycle of a Thread

1. New

 A new thread is always in a new state when it is formed. 
 

2. Runnable State

When a thread is prepared to execute, it is transferred to a runnable state.
 

3. Blocked/Waiting state

A thread is in a blocked or waiting state when it is momentarily dormant.
 

4. Timed Waiting

When a method with a time-out parameter is called, a thread enters a timed waiting state.
 

5. Terminated

A thread may come to an end due to a normal exit or an unusually erroneous event.

What is Thread in java?

In Java, a thread is the course or path followed while a programme is being run. Perhaps a thread is a program's thread of execution. The main thread, which is typically present in all programmes, is provided by the JVM, or Java Virtual Machine, at the beginning of the program's execution. Each thread is given priority. Higher-priority threads are prioritised for execution over lower-priority threads.

Java Thread class

A thread is a programme that starts with the start() method, a method() that is frequently used in this class. This function searches for the run() method, which is also a method of this class and starts running its body.

Java Thread Methods

In this section of the blog, we will see different methods of the Java thread class.

Method Description
activeCount() Returns an approximate count of active threads in the thread group and subgroups of the current thread.
checkAccess() Determines whether the active thread is permitted to change this thread.
clone() Because a Thread cannot be meaningfully copied, it throws the CloneNotSupportedException exception.
currentThread() It gives a reference to the thread object that is presently in use.
dumpStack() Prints the current thread's stack trace to the standard error stream.
enumerate(Thread[] tarray) Copies each active thread in the thread group and any subgroups of the current thread into the provided array.
getId() Returns the thread's identification.
getName() Returns the name of this thread.
getPriority() Returns the priority of this thread.
getState() Provides the thread's state back.

Let us understand all these methods with the help of an example.

Example

class NinjasThreadClass extends Thread {
   private String message;
   public NinjasThreadClass(String message) {
       this.message = message;
   }
   public void run() {
       for (int i = 0; i < 5; i++) {
           System.out.println(message);
           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
   }
}
public class Main {
   public static void main(String[] args) {
       NinjasThreadClass thread = new NinjasThreadClass("Hello Ninjas from thread");
       
       // Set the name of the thread
       thread.setName("NinjasThread");
       
       // Get the name of the thread
       System.out.println("Thread name is: " + thread.getName());
       
       // Set the priority of the thread
       thread.setPriority(Thread.MAX_PRIORITY);
       
       // Get the priority of the thread
       System.out.println("Thread priority is: " + thread.getPriority());
       
       // Check if the thread is alive
       System.out.println("Thread is alive: " + thread.isAlive());
       
       // Start the thread
       thread.start();
       
       try {
       
           // Wait for the thread to finish
           thread.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       
       // Check if the thread is alive after it has finished
       System.out.println("Thread is alive: " + thread.isAlive());
   }
}


Output

Thread name is: NinjasThread
Thread priority is: 10
Thread is alive: false
Hello Ninjas from thread
Hello Ninjas from thread
Hello Ninjas from thread
Hello Ninjas from thread
Hello Ninjas from thread
Thread is alive: false

Thread Creation

There are two primary ways to create threads in Java. The following are the ways: 

  • By extending Thread class: You can create a new class that extends the Thread class and override the run() method to specify the code that the thread should execute. 
     
  • By implementing the Runnable interface: You can create a new class that implements the Runnable interface and override the run() method to specify the code that the thread should execute.

What is Thread Class?

In Java, the Thread class is a built-in class that represents a thread of execution. It provides methods to create and manage threads, as well as methods to control the execution of threads. Some important methods of the Thread class include:

  • start(): starts the thread by calling its run() method
     
  • run(): the method that is executed when the thread is started
     
  • sleep(): causes the thread to pause for a specified amount of time
     
  • join(): waits for the thread to complete its execution
     

Let us understand this with the help of an example.

class NinjasThread extends Thread {
   private String message;
   public NinjasThread(String message) {
       this.message = message;
   }
   public void run() {
       for (int i = 0; i < 5; i++) {
           System.out.println(message);
           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
   }
}
public class Main {
   public static void main(String[] args) {
       NinjasThread thread1 = new NinjasThread("Hello Ninjas from thread 1");
       NinjasThread thread2 = new NinjasThread("Hello Ninjas from thread 2");
       thread1.start();
       thread2.start();
   }
}


Output

Hello Ninjas from thread 1
Hello Ninjas from thread 2
Hello Ninjas from thread 1
Hello Ninjas from thread 2
Hello Ninjas from thread 1
Hello Ninjas from thread 2
Hello Ninjas from thread 1
Hello Ninjas from thread 2
Hello Ninjas from thread 1
Hello Ninjas from thread 2

What is a Runnable Interface?

In Java, the Runnable interface is a built-in interface that is used to define a task that can be executed by a thread. It contains a single method called run() that is used to specify the code that the thread should execute. To use the Runnable interface, you need to create a class that implements the Runnable interface and overrides the run() method. Let us understand this with the help of an example.

class NinjasRunnableInterface implements Runnable {
   private String message;
   public NinjasRunnableInterface(String message) {
       this.message = message;
   }
   public void run() {
       for (int i = 0; i < 5; i++) {
           System.out.println(message);
           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
   }
}
public class Main {
   public static void main(String[] args) {
       NinjasRunnableInterface runnable1 = new NinjasRunnableInterface("Hello Ninjas from runnable 1");
       NinjasRunnableInterface runnable2 = new NinjasRunnableInterface("Hello Ninjas from runnable 2");
       Thread thread1 = new Thread(runnable1);
       Thread thread2 = new Thread(runnable2);
       thread1.start();
       thread2.start();
   }
}


Output

Hello Ninjas from runnable 1
Hello Ninjas from runnable 2
Hello Ninjas from runnable 1
Hello Ninjas from runnable 2
Hello Ninjas from runnable 1
Hello Ninjas from runnable 2
Hello Ninjas from runnable 1
Hello Ninjas from runnable 2
Hello Ninjas from runnable 1
Hello Ninjas from runnable 2

 

Must Read Type Conversion in Java

Thread priority

In Multithreading, every thread has its own priority. It is defined using three constants. The priority of a thread can be set to a number between 1 to 10.

  1. public static int NORM_PRIORITY - It gives the thread a default priority of 5.
     
  2. public static int MIN_PRIORITY- It gives the thread a minimum priority of 1.
     
  3. public static int MAX_PRIORITY- It gives the thread a maximum priority of 10.
     

Methods:

  • getPriority() - It returns the priority of the given thread.
     
  • setPriority(int newpriority) - It changes the priority of the given thread to a new one.
     

IllegalArgumentException is thrown if the value of newpriority does not satisfy 1<=newpriority<=10.

import java.lang.*;
class Mthread extends Thread
{
	public void run()
	{
		System.out.println("Thread Running");
	}
}
public class Main
{
	public static void main(String[] args)
	{
		Mthread m = new Mthread();
		m.start();
		m.setPriority(2);
		System.out.println("Thread Priority of thread m is: " + m.getPriority());
	}
}


Output

Thread Running
Thread Priority of thread m is: 2


Note:

Threads with the highest priority get the chance to execute first. 

The default priority of the Main thread is 5, which can be changed. 

The default priority of a thread depends on the priority of its parent thread.

Thread Scheduling

A thread scheduler in Java determines the thread for execution. A thread in the runnable state is scheduled for execution. However, if two or more threads are in the runnable state, then, based on the priority number and time of arrival, a thread is chosen, and the others are told to wait. The common thread scheduling algorithms are First Come First Serve scheduling, priority scheduling and time-slicing scheduling.

Thread Synchronization

Synchronization is a process that handles resource management. Due to concurrency, multiple threads try to access the same resource simultaneously. Synchronization uses the concept of monitoring to ensure that only one thread gets access to a resource at a time. Every thread has a monitor associated with it that can lock or unlock. Java uses synchronized blocks or methods to synchronize threads. All shared resources are put in this block.

synchronized(objectidentifier) {
  // Access shared resources or code that requires sequential access
}


Practice by yourself on java online compiler.

Related Article Threads in Operating System

Frequently Asked Questions

What is the multithreading in Java?

Multithreading in Java refers to the ability of a program to have multiple threads of execution running concurrently within the same program. A thread can be thought of as a separate sequence of execution within a program.

What is multithreading with example?

Multithreading in Java allows a program to execute multiple threads concurrently. For example, we have a class that implements a Runnable interface. The run() method contains the code that will be executed when the thread is started. We create two instances of the class and pass them to Thread objects. Then, we start both threads using the start() method.

What are the two types of multithreading?

The two types of multithreading are user-level and kernel-level threads. User-level threads also known as green threads or user threads, these are managed entirely by the Java Virtual Machine (JVM) and the Java application. On the other hand, kernel-level threads, also known as native threads, are managed by the operating system's kernel.

What are two advantages of multithreading?

There are several advantages to using multithreading in a program, but the two key advantages are improvement in the performance of a program if we allow multiple threads and the other key advantage is that it enhances responsiveness. Multithreading can also improve the responsiveness of a program by allowing it to handle multiple tasks simultaneously. 

Conclusion

Multithreading and threading concepts play an important role in Java Programming. This blog gives a brief description of the main concepts related to multithreading and Multithreading in Java. It also explains a few thread-related concepts and concludes by listing the advantages and disadvantages of Multithreading in Java.

Recommended Reading:

Check out the official Coding Ninjas Blog site and visit our Library for more.

Also, check out some of the amazing Guided Paths on topics such as Data Structure and Algorithms, Competitive Programming, Basics of C, Basics of Java, etc. along with some Contests and Interview Experiences only on Coding Ninjas Studio

Next article
Life Cycle Of A Thread
Live masterclass