Java Multithreading: Complete Guide with Examples

Multithreading in Java is a process of executing multiple threads at the same time. It helps improve performance by allowing different parts of a program to run concurrently.

What is a Thread in Java?

A thread is a lightweight sub-process. It is the smallest unit of execution inside a program. A Java application can have multiple threads running at the same time.

Example

In a music player application, one thread can play music while another thread handles user input.

Multitasking vs Multithreading

Multitasking Multithreading
Multiple processes run at the same time Multiple threads run inside the same process
Heavyweight Lightweight
More memory required Less memory required

Ways to Create Thread in Java

There are two common ways to create a thread in Java:

  • By extending Thread class
  • By implementing Runnable interface

Creating Thread by Extending Thread Class

In this approach, a class extends the Thread class and overrides the run() method.

class MyThread extends Thread {
    public void run() {
        System.out.println("Thread is running");
    }
}

public class Test {
    public static void main(String[] args) {
        MyThread t = new MyThread();
        t.start();
    }
}

The start() method creates a new thread and internally calls the run() method.

Creating Thread by Implementing Runnable Interface

In this approach, a class implements the Runnable interface and provides implementation for the run() method.

class MyRunnable implements Runnable {
    public void run() {
        System.out.println("Thread is running");
    }
}

public class Test {
    public static void main(String[] args) {
        MyRunnable r = new MyRunnable();
        Thread t = new Thread(r);
        t.start();
    }
}

This approach is recommended when the class already extends another class, because Java does not support multiple inheritance with classes.

Difference Between start() and run()

start() run()
Creates a new thread Does not create a new thread
Calls run() internally Executes like a normal method
Used to start thread execution Contains thread logic
MyThread t = new MyThread();

t.start(); // new thread
t.run();   // normal method call

Thread Life Cycle in Java

A thread goes through different states during execution.

  • New: Thread object is created
  • Runnable: Thread is ready to run
  • Running: Thread is executing
  • Blocked / Waiting: Thread is temporarily inactive
  • Terminated: Thread execution completed

Important Thread Methods

Method Use
start() Starts thread execution
run() Contains thread logic
sleep() Pauses thread temporarily
join() Waits for another thread to complete
yield() Pauses current thread to give chance to another thread

sleep() Method in Java

The sleep() method pauses the current thread for a specified time.

class Test {
    public static void main(String[] args) throws InterruptedException {
        for (int i = 1; i <= 5; i++) {
            System.out.println(i);
            Thread.sleep(1000);
        }
    }
}

join() Method in Java

The join() method makes one thread wait until another thread completes.

class MyThread extends Thread {
    public void run() {
        for (int i = 1; i <= 3; i++) {
            System.out.println(i);
        }
    }
}

public class Test {
    public static void main(String[] args) throws InterruptedException {
        MyThread t = new MyThread();
        t.start();

        t.join();

        System.out.println("Main thread completed");
    }
}

Thread Priority in Java

Every thread has a priority. Thread priority helps the thread scheduler decide which thread should get preference.

  • Thread.MIN_PRIORITY = 1
  • Thread.NORM_PRIORITY = 5
  • Thread.MAX_PRIORITY = 10
Thread t = new Thread();
t.setPriority(Thread.MAX_PRIORITY);

System.out.println(t.getPriority());

Synchronization in Java

Synchronization is used to control access to shared resources by multiple threads. It prevents data inconsistency.

Example Without Synchronization Problem

class Counter {
    int count = 0;

    synchronized void increment() {
        count++;
    }
}

The synchronized keyword allows only one thread at a time to access the method.

Synchronized Block

Instead of synchronizing the whole method, we can synchronize only a specific block of code.

synchronized(this) {
    // critical section
}

Deadlock in Java

Deadlock occurs when two or more threads wait forever for each other to release resources.

Deadlock should be avoided by proper lock ordering and reducing nested locks.

Inter-thread Communication

Inter-thread communication allows synchronized threads to communicate with each other.

Important Methods

  • wait()
  • notify()
  • notifyAll()

These methods are available in the Object class and must be called from synchronized context.

Daemon Thread in Java

A daemon thread is a background thread that provides support to user threads. Garbage Collector is a common example of daemon thread.

Thread t = new Thread();
t.setDaemon(true);

Multithreading Summary

  • Thread is a lightweight sub-process
  • Threads can be created using Thread class or Runnable interface
  • start() creates a new thread
  • run() executes like normal method if called directly
  • Synchronization prevents data inconsistency
  • wait(), notify(), and notifyAll() support inter-thread communication

Java Multithreading FAQ

What is multithreading in Java?

Multithreading is the process of executing multiple threads at the same time.

What is the difference between start() and run()?

start() creates a new thread, while run() executes like a normal method.

Why synchronization is used?

Synchronization is used to prevent data inconsistency when multiple threads access shared resources.