Java Multithreading
Multithreading enables concurrent execution of multiple threads in Java, allowing programs to perform multiple operations simultaneously.
What is a Thread?
A thread is the smallest unit of execution within a process. Java programs can have multiple threads running concurrently.
Creating Threads
Method 1: Extending Thread Class
1class MyThread extends Thread {
2 public void run() {
3 System.out.println("Thread running: " + Thread.currentThread().getName());
4 }
5}
6
7// Usage
8MyThread thread = new MyThread();
9thread.start();Method 2: Implementing Runnable Interface (Preferred)
1class MyTask implements Runnable {
2 public void run() {
3 System.out.println("Task executing: " + Thread.currentThread().getName());
4 }
5}
6
7// Usage
8Thread thread = new Thread(new MyTask());
9thread.start();Method 3: Using Lambda Expressions
1Thread thread = new Thread(() -> {
2 System.out.println("Lambda thread: " + Thread.currentThread().getName());
3});
4thread.start();Thread Lifecycle
- NEW: Thread created but not started
- RUNNABLE: Ready to run or running
- BLOCKED: Waiting for monitor lock
- WAITING: Waiting indefinitely
- TIMED_WAITING: Waiting for specified time
- TERMINATED: Thread execution completed
1Thread thread = new Thread(() -> {
2 try {
3 Thread.sleep(1000); // TIMED_WAITING
4 } catch (InterruptedException e) {
5 e.printStackTrace();
6 }
7});
8
9System.out.println(thread.getState()); // NEW
10thread.start();
11System.out.println(thread.getState()); // RUNNABLESynchronization
The Problem: Race Conditions
1class Counter {
2 private int count = 0;
3
4 public void increment() {
5 count++; // Not thread-safe!
6 }
7
8 public int getCount() {
9 return count;
10 }
11}Solution: Synchronized Methods
1class ThreadSafeCounter {
2 private int count = 0;
3
4 public synchronized void increment() {
5 count++; // Thread-safe
6 }
7
8 public synchronized int getCount() {
9 return count;
10 }
11}Synchronized Blocks
1class BankAccount {
2 private double balance;
3
4 public void withdraw(double amount) {
5 synchronized(this) { // Lock on this object
6 if (balance >= amount) {
7 balance -= amount;
8 }
9 }
10 }
11}Thread Communication
wait() and notify()
1class ProducerConsumer {
2 private Queue<Integer> queue = new LinkedList<>();
3 private int capacity = 5;
4
5 public void produce(int item) throws InterruptedException {
6 synchronized(this) {
7 while (queue.size() == capacity) {
8 wait(); // Wait for consumer
9 }
10 queue.add(item);
11 notify(); // Notify consumer
12 }
13 }
14
15 public int consume() throws InterruptedException {
16 synchronized(this) {
17 while (queue.isEmpty()) {
18 wait(); // Wait for producer
19 }
20 int item = queue.remove();
21 notify(); // Notify producer
22 return item;
23 }
24 }
25}Concurrency Utilities
ExecutorService
1ExecutorService executor = Executors.newFixedThreadPool(5);
2
3executor.submit(() -> {
4 System.out.println("Task 1");
5});
6
7executor.submit(() -> {
8 System.out.println("Task 2");
9});
10
11executor.shutdown(); // Important: shutdown the executorFuture and Callable
1ExecutorService executor = Executors.newSingleThreadExecutor();
2
3Future<Integer> future = executor.submit(() -> {
4 Thread.sleep(1000);
5 return 42;
6});
7
8// Do other work while task runs
9System.out.println("Doing other work...");
10
11// Get result (blocks if not ready)
12Integer result = future.get();
13System.out.println("Result: " + result);
14
15executor.shutdown();Thread Pools
Fixed Thread Pool
1ExecutorService executor = Executors.newFixedThreadPool(4);
2// Always 4 threads availableCached Thread Pool
1ExecutorService executor = Executors.newCachedThreadPool();
2// Creates threads as needed, reuses idle threadsSingle Thread Executor
1ExecutorService executor = Executors.newSingleThreadExecutor();
2// Only one thread at a timeCommon Issues
Deadlocks
1// Avoid this pattern!
2public void method1() {
3 synchronized(lock1) {
4 synchronized(lock2) {
5 // Do work
6 }
7 }
8}
9
10public void method2() {
11 synchronized(lock2) {
12 synchronized(lock1) {
13 // Do work
14 }
15 }
16}Starvation
Low-priority threads may never get CPU time.
Livelock
Threads keep responding to each other but make no progress.
Best Practices
- Use ExecutorService instead of creating threads directly
- Prefer immutable objects when possible
- Use concurrent collections (ConcurrentHashMap, CopyOnWriteArrayList)
- Minimize synchronized scope
- Always shutdown ExecutorService
- Handle InterruptedException properly
- Use volatile for variables accessed by multiple threads
Modern Java Concurrency
Java 8+ introduced many improvements:
- CompletableFuture for asynchronous programming
- Parallel streams for data processing
- Improved atomic classes
- Lock interface for flexible locking
Multithreading is essential for building responsive and scalable Java applications, especially in modern multi-core systems.

