11.1 Creating Threads: Thread and Runnable
A Thread is an independent path of execution running concurrently within a single program process, sharing heap memory while maintaining its own dedicated stack space.
Two Mechanisms to Create Threads
- 1. Extending
Thread: Create a subclass ofThreadand override itsrun()method. (Disadvantage: consumes the class's single inheritance slot). - 2. Implementing
Runnable(Best Practice): Pass aRunnablefunctional interface instance into aThreadconstructor. Keeps inheritance open for domain models:Runnable task = () -> System.out.println("Running in a new thread: " + Thread.currentThread().getName()); Thread t = new Thread(task); t.start(); // Spawns a new concurrent OS thread!
Always call .start(), NEVER .run() directly! Calling .run() executes the code synchronously on the current caller thread like a normal method. Calling .start() signals the JVM to allocate a new call stack and register a concurrent thread with the OS scheduler.
11.2 Synchronization
When multiple concurrent threads read and write shared mutable state without coordination, a race condition occurs — producing corrupted or unpredictable data depending on arbitrary CPU scheduling timing.
The synchronized Keyword
Every Java object contains an intrinsic Monitor Lock. Applying synchronized guarantees mutual exclusion (Mutex): only one thread can hold the lock and execute the protected block or method at any given moment. Other threads must wait their turn in the Blocked state:
class BankAccount {
private int balance = 1000;
// Synchronized method locks on the current instance (this)
public synchronized void withdraw(int amount) {
if (balance >= amount) {
balance -= amount;
}
}
}
An unpredictable bug that occurs when multiple threads access shared data concurrently without synchronization, and the outcome depends on the unpredictable timing of which thread happens to run first.
💡 Placement & Interview Deep-Dive
- What is the difference between
wait()andThread.sleep()?wait()is a method ofjava.lang.Object. It releases the monitor lock, allowing other waiting threads to enter the synchronized block, and waits fornotify()/notifyAll().Thread.sleep()is a static method ofThread. It pauses execution for a specified duration WITHOUT releasing any held monitor locks.
- What does the
volatilekeyword do? Marking a variablevolatileguarantees Memory Visibility across threads: reads and writes bypass local CPU L1/L2 caches and write directly to main RAM, establishing a happens-before relationship. It also prevents CPU instruction reordering. Note:volatiledoes NOT guarantee atomicity for compound operations likecount++! - What is a Deadlock? A situation where two or more threads are permanently blocked, each holding a lock that the other needs (e.g. Thread 1 holds Lock A waiting for Lock B; Thread 2 holds Lock B waiting for Lock A).