Java supports multithreading to perform multiple tasks concurrently. Threads allow efficient use of CPU cores, improve performance, and enable responsive applications. They are a core part of Java concurrency.
What is a Thread?
A thread is a lightweight unit of execution within a process.
A Java application starts with a single main thread but can spawn multiple threads to run tasks in parallel.
Ways to Create Threads
1. Extending Thread class
class MyThread extends Thread {
public void run() {
System.out.println("Thread running");
}
}
new MyThread().start();
2. Implementing Runnable
class MyTask implements Runnable {
public void run() {
System.out.println("Task executed");
}
}
new Thread(new MyTask()).start();
3. Using Lambda (Java 8+)
new Thread(() -> System.out.println("Lambda thread")).start();
4. Using ExecutorService (Preferred)
ExecutorService exec = Executors.newFixedThreadPool(5);
exec.submit(() -> System.out.println("Task"));
exec.shutdown();
Thread States
| State | Meaning |
|---|---|
| NEW | Created but not started |
| RUNNABLE | Running or ready to run |
| BLOCKED | Waiting for monitor lock |
| WAITING | Waiting indefinitely |
| TIMED_WAITING | Waiting with timeout |
| TERMINATED | Finished |
Thread Lifecycle
NEW → RUNNABLE → WAITING/BLOCKED → RUNNABLE → TERMINATED
Common Thread Methods
| Method | Purpose |
|---|---|
start() |
Starts thread |
run() |
Code executed by thread |
sleep(ms) |
Pause thread |
join() |
Wait for thread to finish |
yield() |
Hint to switch threads |
interrupt() |
Interrupt thread |
Synchronization
Used to prevent race conditions when multiple threads access shared resources.
synchronized void increment() {
count++;
}
Or using intrinsic locks:
synchronized(obj) {
// critical section
}
Deadlock
Occurs when two threads wait for each other’s resources — both get stuck forever.
Thread A has Lock1 → waiting for Lock2
Thread B has Lock2 → waiting for Lock1
👉 Avoid by always acquiring locks in the same order.
Thread Pool (Executor Framework)
Better than creating threads manually.
ExecutorService pool = Executors.newFixedThreadPool(10);
pool.submit(task);
pool.shutdown();
Benefits:
- Reuses threads
- Improves performance
- Manages queue & scheduling
Future & Callable (Return Values from Threads)
Callable<Integer> task = () -> 10 * 2;
Future<Integer> result = executor.submit(task);
System.out.println(result.get()); // 20
Virtual Threads (Java 19+ / 21)
Lightweight threads — thousands can be created with minimal overhead.
Thread.startVirtualThread(() -> {
// task goes here
});
👉 Game changer for concurrency & high-throughput apps.
Summary Table
| Concept | Purpose |
|---|---|
| Thread | Unit of execution |
| Runnable | Task without return |
| Callable | Task with return |
| ExecutorService | Manages thread pool |
| synchronized | Prevents race conditions |
| Future | Get result of async task |
| Virtual Thread | Lightweight concurrency |
Top comments (0)