Multithreading enables performance and responsiveness, but coordination between threads is critical. Java provides wait()
, notify()
, and notifyAll()
as native methods to facilitate thread communication.
This tutorial unpacks how these methods work, when to use them, and how to avoid concurrency pitfalls in Java applications.
🧵 What is Thread Communication?
Thread communication in Java allows threads to cooperate over shared data, avoiding race conditions and unnecessary CPU cycles from busy waiting.
Real-world Analogy
Think of a delivery system: a producer thread (sender) prepares a parcel and puts it in a dropbox. A consumer thread (delivery boy) waits until there is a parcel. The consumer sleeps (wait()
), and the producer wakes it up (notify()
) once the parcel is ready.
🚦 Thread Lifecycle Overview
Java threads move between the following states:
- NEW → RUNNABLE → RUNNING → WAITING/BLOCKED → TERMINATED
The wait()
method transitions the thread to the WAITING state, pausing its execution.
🔄 Core Thread Communication Methods
wait()
- Causes the current thread to release the monitor and go into waiting state.
- Only resumes when
notify()
ornotifyAll()
is called. - Must be used inside a synchronized block.
notify()
- Wakes one waiting thread on the object's monitor.
notifyAll()
- Wakes all threads waiting on the object's monitor.
synchronized (sharedLock) {
while (!conditionMet) {
sharedLock.wait();
}
// Do work once condition is true
}
synchronized (sharedLock) {
conditionMet = true;
sharedLock.notify(); // or notifyAll()
}
⚠️ Key Rules to Remember
- All methods must be called within synchronized blocks.
- Always use
wait()
inside awhile
loop, notif
, to prevent spurious wakeups. notify()
randomly picks one thread;notifyAll()
wakes all.
👷♂️ Producer-Consumer Example
class Buffer {
private boolean full = false;
synchronized void produce() throws InterruptedException {
while (full) wait();
System.out.println("Produced item");
full = true;
notify();
}
synchronized void consume() throws InterruptedException {
while (!full) wait();
System.out.println("Consumed item");
full = false;
notify();
}
}
🔁 wait/notify vs Modern Alternatives
Goal | Preferred Tool |
---|---|
Thread coordination | wait(), notify(), notifyAll() |
Producer-consumer | BlockingQueue |
Task completion | Future, CompletableFuture |
Scheduling | Executors, ForkJoinPool |
📌 What's New in Java Concurrency (8–21)
- Java 8: Lambdas,
CompletableFuture
, parallel streams - Java 9: Flow API for reactive programming
- Java 11: Minor improvements in
CompletableFuture
- Java 21: Structured concurrency, virtual threads, scoped values (Project Loom)
🛠 Best Practices
- Keep synchronized sections short and efficient.
- Avoid calling wait/notify on
this
unless it's safe. - Prefer higher-level constructs like
BlockingQueue
when applicable. - Ensure proper lock release using try-finally blocks.
❓ FAQ
-
Can
wait()
be used outsidesynchronized
?
No. It throwsIllegalMonitorStateException
. -
Why use
while
instead ofif
withwait()
?
To protect against spurious wakeups. -
Is
notify()
guaranteed to wake the right thread?
No, it's non-deterministic.notifyAll()
is safer. -
What is a spurious wakeup?
When a thread wakes without being notified. -
How is
join()
different fromwait()
?join()
waits for thread completion, not for condition. -
Can I use
notify()
withoutwait()
?
Yes, but it does nothing if no thread is waiting. -
What happens if a thread is never notified?
It remains in WAITING state indefinitely (potential deadlock). -
Should I use
notifyAll()
always?
Use it when multiple waiting threads need rechecking. -
Are
wait()
andnotify()
deprecated?
No, but newer constructs often provide better abstraction. -
What is the monitor object?
It's the object whose lock is acquired in asynchronized
block.
🧾 Conclusion and Key Takeaways
wait()
,notify()
, andnotifyAll()
are essential for low-level thread coordination.- Always use them with synchronization and within loops.
- In modern Java, consider high-level alternatives when available.
- Understanding these core tools is key for writing responsive and correct concurrent applications.