Multithreading in Java: Thread Life Cycle, Creation, Synchronization & Thread Groups


 

Java Multithreading

Master Concurrent Programming in Java

Introduction

Have you ever wondered how your computer plays music, downloads files, and lets you browse the internet—all at the same time? That magic comes from multithreading, and in Java, it's one of the most powerful features available for building responsive, high-performance applications.


In this article, we'll explore multithreading in Java, including the thread life cycle, how to create threads in two different ways, the importance of synchronization, and how thread groups help manage multiple threads.

What is Multithreading in Java?

In simple terms, multithreading means running multiple parts of a program at the same time. A thread is the smallest unit of a process.

Process

An independent program in execution.

Thread

A lightweight sub-process that shares memory with other threads.

Advantages of multithreading:

✓ Better CPU utilization

✓ Faster program execution

✓ Smooth user experience

Key Features of Multithreading

Concurrency

Multiple tasks run at the same time.

Resource Sharing

Threads share memory and resources.

Scalability

Perfect for multi-core processors.

Thread Life Cycle

A thread in Java goes through different states, managed by the Thread Scheduler.

New

Thread is created but not yet started

Runnable

Ready but waiting for CPU time

Running

Currently executing

Waiting/Blocked

Waits for resources

Terminated

Finished execution

Thread Life Cycle in Java

Complete State Transitions with Methods

NEW

New State

Thread object created but not started

new Thread()
RUNNABLE

Runnable State

Ready to run or currently running

start()
BLOCKED

Blocked State

Waiting for monitor lock

synchronized
WAITING

Waiting State

Indefinitely waiting for another thread

wait()
TERMINATED

Terminated State

Thread has finished execution

run() ends
start()
synchronized block
wait()
run() completes
lock acquired
notify()/notifyAll()
TIMED_WAITING

Timed Waiting State

Thread waits for a specified period

sleep(time)
wait(time)
join(time)

Key Methods for State Transitions

Creation & Start

new Thread() - Creates new thread
start() - Moves to RUNNABLE

Blocking

synchronized - Can cause BLOCKED
lock.lock() - Explicit locking

Waiting

wait() - WAITING state
notify() - Wake up waiting thread

Timed Operations

sleep(ms) - TIMED_WAITING
join(ms) - Wait for thread

Termination

run() - Method completes
interrupt() - Request termination

State Checking

getState() - Get current state
isAlive() - Check if running

🔄 Arrows show state transitions | 📋 Methods trigger the transitions

Thread states are managed by the JVM Thread Scheduler

Thread Class and Runnable Interface

Java provides two ways to create threads:

Extending Thread Class

Easy, but Java doesn't allow multiple inheritance.

Implementing Runnable

More flexible, preferred in real-world projects.

Creating Thread by Extending Thread Class

class MyThread extends Thread {
    public void run() {
        System.out.println("Thread is running by extending Thread class.");
    }
    public static void main(String args[]) {
        MyThread t1 = new MyThread();
        t1.start();
    }
}
Output: Thread is running by extending Thread class.

Creating Thread by Implementing Runnable Interface

class MyRunnable implements Runnable {
    public void run() {
        System.out.println("Thread is running by implementing Runnable interface.");
    }
    public static void main(String args[]) {
        MyRunnable obj = new MyRunnable();
        Thread t1 = new Thread(obj);
        t1.start();
    }
}
Output: Thread is running by implementing Runnable interface.

Thread Priorities

Java assigns each thread a priority (1–10). By default, it's 5.

Thread t1 = new Thread();
t1.setPriority(8);
System.out.println("Thread Priority: " + t1.getPriority());

Synchronization in Java

Imagine two people editing the same document at the same time—it leads to chaos. That's why we need synchronization in threads.

Synchronized Method

Locks the entire method

Synchronized Block

Locks a specific section of code

Synchronized Method Example

class Counter {
    int count = 0;
    synchronized void increment() {
        count++;
    }
}
class TestSync {
    public static void main(String args[]) throws InterruptedException {
        Counter c = new Counter();
        Thread t1 = new Thread(() -> { for(int i=0;i<1000;i++) c.increment(); });
        Thread t2 = new Thread(() -> { for(int i=0;i<1000;i++) c.increment(); });
        t1.start(); t2.start();
        t1.join(); t2.join();
        System.out.println("Count: " + c.count);
    }
}
Output: Count: 2000

Synchronized Block Example

class Display {
    void show(String msg) {
        synchronized(this) {
            System.out.println("Hello, " + msg);
        }
    }
}
class TestBlock {
    public static void main(String args[]) {
        Display d = new Display();
        Thread t1 = new Thread(() -> d.show("Alice"));
        Thread t2 = new Thread(() -> d.show("Bob"));
        t1.start(); t2.start();
    }
}
Output:
Hello, Alice
Hello, Bob

Thread Groups in Java

Thread groups let you manage multiple threads together.

class MyThread extends Thread {
    MyThread(ThreadGroup g, String name) {
        super(g, name);
    }
    public void run() {
        System.out.println(getName() + " is running.");
    }
}
class TestGroup {
    public static void main(String args[]) {
        ThreadGroup tg = new ThreadGroup("MyGroup");
        MyThread t1 = new MyThread(tg, "Thread-1");
        MyThread t2 = new MyThread(tg, "Thread-2");
        t1.start(); t2.start();
        System.out.println("Thread Group Name: " + tg.getName());
    }
}
Output:
Thread-1 is running.
Thread-2 is running.
Thread Group Name: MyGroup

Practical Applications of Multithreading

Games

Handling animations, background music, and controls simultaneously.

Servers

Managing multiple client requests.

GUI Applications

Keeping apps responsive while performing tasks.

Best Practices for Multithreading

✓ Avoid deadlock by proper resource management

✓ Keep threads lightweight

✓ Use Executors framework instead of manually creating threads

Conclusion

Multithreading in Java is like having multiple hands working together—efficient, fast, and smooth. From understanding the thread life cycle to creating threads in two ways, handling synchronization, and managing thread groups, you now have a complete picture of how Java handles concurrency.

Frequently Asked Questions

Q1: What is the difference between a process and a thread?

A process is an independent program, while a thread is a lightweight sub-process sharing memory with others.

Q2: Which is better: Thread class or Runnable interface?

Runnable is generally better as it supports multiple inheritance and reusability.

Q3: How do we handle thread safety?

By using synchronization, locks, or concurrent utilities.

Q4: Can we restart a thread in Java?

No, once a thread is terminated, it cannot be restarted.

Q5: What is a daemon thread?

A background thread that provides services to other threads (like garbage collection).


Post a Comment

0 Comments