Multithreading is one of the most powerful features of Java that allows you to execute multiple tasks simultaneously. Whether you’re building high-performance backend systems or scalable applications, understanding Java threads is essential.
In this guide, we’ll explore Java threads from basic concepts to advanced concurrency techniques.
📌 What is a Thread in Java?
A thread is the smallest unit of execution within a program. Java allows multiple threads to run concurrently, making applications faster and more efficient.
👉 Real-life example:
- Listening to music 🎵 while downloading a file 📥
- Both tasks run in parallel → multithreading
⚙️ Process vs Thread
| Feature | Process | Thread |
|---|---|---|
| Definition | Independent program | Part of a process |
| Memory | Separate memory | Shared memory |
| Overhead | High | Low |
| Speed | Slower | Faster |
🧵 Creating Threads in Java
✅ 1. Extending Thread Class
class MyThread extends Thread {
public void run() {
System.out.println("Thread is running");
}
}
public class Main {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
}
}
✅ 2. Implementing Runnable Interface (Recommended)
class MyRunnable implements Runnable {
public void run() {
System.out.println("Thread running using Runnable");
}
}
public class Main {
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable());
t.start();
}
}
👉 Why Runnable?
- Supports multiple inheritance
- Better design practice
✅ 3. Using Lambda (Java 8+)
Thread t = new Thread(() -> {
System.out.println("Thread using Lambda");
});
t.start();
🔄 Thread Lifecycle
A thread goes through different states:
- New
- Runnable
- Running
- Blocked/Waiting
- Terminated
⏱️ Important Thread Methods
| Method | Description |
|---|---|
start() | Starts thread |
run() | Contains logic |
sleep() | Pause execution |
join() | Wait for thread to finish |
yield() | Pause and give chance to others |
🔐 Thread Synchronization
When multiple threads access shared resources, it can lead to data inconsistency.
❌ Problem Example (Race Condition)
class Counter {
int count = 0;
void increment() {
count++;
}
}
✅ Solution: synchronized
class Counter {
int count = 0;
synchronized void increment() {
count++;
}
}
👉 Ensures only one thread executes at a time.
🔒 Locks in Java
Java provides advanced locking mechanisms via java.util.concurrent
import java.util.concurrent.locks.ReentrantLock;
ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
// critical section
} finally {
lock.unlock();
}
🧠 Inter-Thread Communication
Threads can communicate using:
wait()notify()notifyAll()
synchronized(obj) {
obj.wait();
obj.notify();
}
🧵 Thread Pools (Executor Framework)
Creating too many threads is costly. Use thread pools instead.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.submit(() -> {
System.out.println("Task executed");
});
executor.shutdown();
👉 Benefits:
- Reuse threads
- Better performance
- Controlled concurrency
⚡ Callable & Future
Unlike Runnable, Callable returns a value.
import java.util.concurrent.*;
Callable<Integer> task = () -> 10 + 20;
Future<Integer> result = Executors.newSingleThreadExecutor().submit(task);
System.out.println(result.get());
🚀 Advanced Concurrency Concepts
🔹 Fork/Join Framework
Used for parallel processing:
ForkJoinPool pool = new ForkJoinPool();
🔹 Atomic Variables
Thread-safe operations without synchronization:
import java.util.concurrent.atomic.AtomicInteger;
AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet();
🔹 CompletableFuture (Modern Async)
CompletableFuture.supplyAsync(() -> "Hello")
.thenApply(result -> result + " Java")
.thenAccept(System.out::println);
⚠️ Common Thread Problems
❌ Deadlock
Two threads waiting for each other forever
❌ Race Condition
Multiple threads modifying shared data
❌ Starvation
One thread never gets CPU time
🧪 Best Practices
✔ Use ExecutorService instead of manual threads
✔ Avoid shared mutable state
✔ Prefer immutable objects
✔ Use high-level APIs (CompletableFuture)
✔ Always release locks properly
🎯 Conclusion
Java threads are essential for building high-performance and scalable applications. From basic thread creation to advanced concurrency frameworks, mastering threads will significantly improve your development skills.
👉 Start simple, then move to:
- Executor Framework
- CompletableFuture
- Reactive programming