Unlock Your Python Backend Career: Build 30 Projects in 30 Days. Join now for just $54

Introduction to Multithreading

by Ayush Shrivastava

.

Updated Mon Jul 07 2025

.
Introduction to Multithreading

In today's fast-paced digital world, where users expect lightning-fast responses and seamless experiences, the performance and responsiveness of applications are more important than ever. Whether you're building a simple desktop app, a mobile game, or a large-scale web platform, users won't tolerate laggy or unresponsive behavior. To meet these expectations, developers must design systems that can handle multiple tasks efficiently and simultaneously.

One of the most effective techniques to boost application performance is multitasking, the ability to run more than one task at a time. For instance, think about your daily use of a computer or smartphone: you might be watching a video, downloading files in the background, typing notes, and receiving real-time notifications, all at once. This is multitasking in action.

In the world of Java programming, multitasking is commonly achieved using threads. Threads allow different parts of a program to execute concurrently, leading to better CPU utilization and faster application response times. Threads are particularly useful in scenarios where a program needs to perform background tasks, like handling user inputs, performing file operations, or making network requests, without freezing the main user interface.

Understanding how multitasking and multithreading work in Java is essential for any developer aiming to build high-performance, scalable applications. Whether you are developing standalone software, interactive games, or enterprise-level web applications, leveraging Java’s multithreading capabilities can significantly enhance your application’s efficiency and user experience.

In this blog, we'll break down the concept of multitasking in Java into simple terms. We'll cover its types, how threads work, how to create them, and the key differences between threads and processes. Along the way, we'll also look at practical examples and code snippets to help you understand each concept clearly.

Let’s get started and explore how Java enables multitasking through threads, step by step.

What is Single Tasking?

Single tasking means the system can perform only one task at a time. The processor stays idle during input/output operations, leading to poor utilization.

Example

DOS (Disk Operating System)

Only one program can run at a time.

What is Multi-tasking?

Multitasking allows the processor to handle multiple tasks at the same time, improving efficiency and performance by reducing idle time.

Example

Windows OS, where a user can:

  • Listen to music

  • Download a file

  • Write a document

  • Chat with a friend at the same time

Types of Multitasking in Java

There are two ways to achieve multitasking:

1. Processor-based Multitasking

  • Executing multiple independent tasks.

  • Each task has its own memory and resources.

  • Handled by the operating system.

Example:

  • Running a Java program

  • Playing music

  • Downloading files

  • Copying software

  • Browsing websites

2. Thread-based Multitasking

  • Executing multiple parts of the same program.

  • Tasks may share memory and resources.

  • Managed by the programming language, like Java.

Example:

Games and web applications where animations, sound, and user input run in parallel.

Difference Between Thread and Process

image (49).png

Aspect

Process

Thread

Definition

Independent program in execution

Sub-part (lightweight) of a process

Memory

Has its own separate memory

Shares memory with other threads of the same process

Creation Speed

Slower and uses more resources

Faster and uses fewer resources

Communication

Complex (via IPC mechanisms)

Easy (uses shared memory)

Crash Impact

One process crash doesn't affect others

One thread crash can affect the entire process

What is a Thread in Java?

A thread is a lightweight sub-process that allows multitasking within a single program.

Main Thread:

Every Java application has a default thread called the main thread, which starts from the main() method.

How to Get Information About the Current Thread in Java

In Java, every application starts with a default thread known as the main thread. This thread is created by the Java Virtual Machine (JVM) and is responsible for executing the main() method of your class.

To retrieve information about the currently running thread, Java provides a method called

Thread.currentThread(). This method returns a reference to the thread that is currently executing the code.

public class MasteringBackend { public static void main(String[] args) { // Get the reference of the currently running thread Thread currentThread = Thread.currentThread(); // Display the thread information System.out.println("Current Thread Information:"); System.out.println("Thread Name : " + currentThread.getName()); System.out.println("Thread ID : " + currentThread.getId()); System.out.println("Thread Priority : " + currentThread.getPriority()); System.out.println("Thread State : " + currentThread.getState()); System.out.println("Thread Group : " + currentThread.getThreadGroup().getName()); } }

In this example, we use the Thread class in Java, which provides detailed information about the thread. Since the main thread is executing, the output will appear as follows:

Output

Current Thread Information: Thread Name : main Thread ID : 1 Thread Priority : 5 Thread State : RUNNABLE Thread Group : main

Key Methods from Thread Class:

  • getName()

    Returns the name of the thread.

    • Default value is "main".

  • getId()

    • Returns a unique identifier for the thread.

  • getPriority()

    • Returns the thread’s priority.

    • Default is 5 (Thread.NORM_PRIORITY).

  • getState()

    • Returns the current state of the thread.

    • Possible states: NEW, RUNNABLE, WAITING, TIMED_WAITING, BLOCKED, TERMINATED.

  • getThreadGroup()

    • Returns the thread group the thread belongs to.

    • Typically "main" for the main thread.

Life Cycle of a Thread

image (50).pngA thread goes through different phases:

  1. New: Thread object is created.

  2. Runnable: start() is called, ready to run.

  3. Running: Chosen by the thread scheduler to run.

  4. Waiting: Waiting for another thread.

  5. Terminated: Task is completed.

Thread Priority in Java

In Java, each thread has a priority, which is an integer value between 1 (MIN_PRIORITY) and 10 (MAX_PRIORITY). The default priority is 5, which is represented by Thread.NORM_PRIORITY.

Thread priority is used as a hint to the thread scheduler to determine the order in which threads are scheduled for execution. However, Java does not guarantee that a higher-priority thread will always run before a lower-priority one. It depends on the thread scheduler implementation, which is platform-dependent.

Assigning priorities can be useful in scenarios where certain tasks are more critical and should be given preference over others.

Example

public class MasteringBackend { public static void main(String[] args) { // Create three threads using anonymous classes Thread lowPriorityThread = new Thread(() -> { System.out.println("Low Priority Thread is running..."); }); Thread normalPriorityThread = new Thread(() -> { System.out.println("Normal Priority Thread is running..."); }); Thread highPriorityThread = new Thread(() -> { System.out.println("High Priority Thread is running..."); }); // Set priorities lowPriorityThread.setPriority(Thread.MIN_PRIORITY); // Priority = 1 normalPriorityThread.setPriority(Thread.NORM_PRIORITY); // Priority = 5 highPriorityThread.setPriority(Thread.MAX_PRIORITY); // Priority = 10 // Print the priorities for understanding System.out.println("Low Priority Thread Priority : " + lowPriorityThread.getPriority()); System.out.println("Normal Priority Thread Priority : " + normalPriorityThread.getPriority()); System.out.println("High Priority Thread Priority : " + highPriorityThread.getPriority()); // Start all threads lowPriorityThread.start(); normalPriorityThread.start(); highPriorityThread.start(); } }

Output

Low Priority Thread Priority : 1 Normal Priority Thread Priority : 5 High Priority Thread Priority : 10 High Priority Thread is running... Normal Priority Thread is running... Low Priority Thread is running...

Creating Threads in Java

In Java, multithreading is achieved by creating and running multiple threads. A thread in Java can be created using either:

  1. Extending the Thread class

  2. Implementing the Runnable interface

Both approaches require overriding the run() method, which contains the code that will be executed by the thread.

1 Extending the Thread Class

This is the simplest way to create a thread. Here, you create a new class that extends the Thread class and override its run() method.

Steps:

  1. Create a class that extends Thread.

  2. Override the run() method to define the thread’s task.

  3. Create an object of the class.

  4. Call the start() method to begin thread execution.

Syntax:

class MyThread extends Thread { public void run() { // Code to execute in a new thread } }

Example

class MyThread extends Thread { public void run() { System.out.println("Thread is running using Thread class..."); } } public class MasteringBackend { public static void main(String[] args) { MyThread mt = new MyThread(); // Step 3: Create thread object mt.start(); // Step 4: Start the thread (calls run internally) } }

Output

 Thread is running using Thread class..

2. Implementing the Runnable Interface

This approach is preferred when you want your class to extend another class (since Java doesn't support multiple inheritance with classes). You implement the Runnable interface and pass the instance to a Thread object.

Steps:

  1. Create a class that implements Runnable.

  2. Override the run() method.

  3. Create an object of that class.

  4. Create a Thread object and pass the Runnable instance to it.

  5. Call start() on the Thread object

Syntax:

class MyRunnable implements Runnable { public void run() { // Code to execute in a new thread } }

Example

class MyRunnable implements Runnable { public void run() { System.out.println("Thread is running using Runnable interface..."); } } public class MasteringBackend { public static void main(String[] args) { MyRunnable mr = new MyRunnable(); // Step 3 Thread t = new Thread(mr); // Step 4 t.start(); // Step 5 } }

Output

 Thread is running using Runnable interface...

Course image
Become a Java Backend Engineeer today

All-in-one Java course for learning backend engineering with Java. This comprehensive course is designed for Java developers seeking proficiency in Java.

Start Learning Now

Whenever you're ready

There are 4 ways we can help you become a great backend engineer:

The MB Platform

Join 1000+ backend engineers learning backend engineering. Build real-world backend projects, learn from expert-vetted courses and roadmaps, track your learnings and set schedules, and solve backend engineering tasks, exercises, and challenges.

The MB Academy

The “MB Academy” is a 6-month intensive Advanced Backend Engineering BootCamp to produce great backend engineers.

Join Backend Weekly

If you like post like this, you will absolutely enjoy our exclusive weekly newsletter, Sharing exclusive backend engineering resources to help you become a great Backend Engineer.

Get Backend Jobs

Find over 2,000+ Tailored International Remote Backend Jobs or Reach 50,000+ backend engineers on the #1 Backend Engineering Job Board

Backend Tips, Every week

Backend Tips, Every week