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
🔄 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(); } }
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(); } }
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); } }
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(); } }
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()); } }
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).
0 Comments
If you have any doubts, Please let me know