Multithreading in Java

Expert Answer & Key Takeaways

A comprehensive guide to Java Multithreading: Creating threads, thread lifecycle, synchronization, and the Runnable interface.

Multithreading in Java

Multithreading is a core feature of Java that allows concurrent execution of two or more parts of a program for maximum utilization of the CPU. Each part of such a program is called a Thread.

1. Thread vs. Process

  • Process: A process is a program in execution. It is 'heavyweight' because it has its own separate memory area (address space). Switching between processes is slow.
  • Thread: A thread is a lightweight sub-process; the smallest unit of processing. Multiple threads share the same memory area allocated to their parent process. Switching between threads is much faster.

2. The Thread Lifecycle

A thread in Java goes through several states during its lifetime (managed by the Thread Scheduler):
  1. New: The thread is created (Thread t = new Thread();) but not yet started.
  2. Runnable: After t.start() is called. The thread is ready to run and waiting for CPU time.
  3. Running: The CPU is actively executing the thread's run() method.
  4. Non-Runnable (Blocked/Waiting): The thread is alive but cannot run because it is waiting for a resource (like I/O or a lock) or sleep() was called.
  5. Terminated (Dead): The run() method has finished executing. The thread is dead and cannot be restarted.

3. How to Create a Thread

There are two ways to create a thread in Java:

3.1 By Extending the Thread Class

You create a class that inherits from java.lang.Thread and override its run() method.
class MyThread extends Thread { public void run() { System.out.println("Thread is running..."); } } public class Main { public static void main(String[] args) { MyThread t1 = new MyThread(); t1.start(); // This automatically calls the run() method in a new call stack } }

3.2 By Implementing the Runnable Interface (Recommended)

Since Java does not support multiple inheritance, extending the Thread class limits your ability to extend another class. Implementing Runnable is the preferred approach.
class MyRunnable implements Runnable { public void run() { System.out.println("Thread using Runnable is running..."); } } public class Main { public static void main(String[] args) { MyRunnable m1 = new MyRunnable(); Thread t1 = new Thread(m1); // Pass the runnable to a new Thread object t1.start(); } }

4. Important Thread Methods

  • start(): Starts the execution of the thread. JVM calls the run() method.
  • run(): Contains the actual logic the thread will execute.
  • sleep(milliseconds): Pauses the currently executing thread for a specified time.
  • join(): Waits for a thread to die. If thread A calls B.join(), A will stop executing until B finishes.
  • setPriority(int): Changes the priority of the thread (1 is MIN, 5 is NORM, 10 is MAX).

5. Synchronization

When multiple threads try to access the same shared resource (like a variable or a file) simultaneously, it can lead to data inconsistency. This is called a Race Condition.
  • Solution: We use the synchronized keyword. It locks the resource so that only one thread can access it at a time. Other threads must wait until the lock is released.
synchronized void printData() { // Only one thread can execute this block at a time }

Course4All Editorial Board

Verified Expert

Subject Matter Experts

Comprising experienced educators and curriculum specialists dedicated to providing accurate, exam-aligned preparation material.

Pattern: 2026 Ready
Updated: Weekly