How to Use wait and notify in Java for Thread Communication
In Java,
wait() pauses the current thread until another thread calls notify() or notifyAll() on the same object. These methods must be called inside a synchronized block to coordinate threads safely and avoid race conditions.Syntax
The wait() and notify() methods belong to the Object class and are used for thread communication inside synchronized blocks.
wait(): Causes the current thread to wait until another thread callsnotify()ornotifyAll()on the same object.notify(): Wakes up one waiting thread on the same object.notifyAll(): Wakes up all waiting threads on the same object.
All calls must be inside a synchronized block on the same object to avoid illegal monitor state exceptions.
java
synchronized (obj) { obj.wait(); // Current thread waits // or obj.notify(); // Wakes one waiting thread // or obj.notifyAll(); // Wakes all waiting threads }
Example
This example shows two threads communicating using wait() and notify(). The Producer thread waits for a signal, and the Consumer thread sends the signal to continue.
java
public class WaitNotifyExample { private static final Object lock = new Object(); private static boolean ready = false; public static void main(String[] args) throws InterruptedException { Thread producer = new Thread(() -> { synchronized (lock) { try { System.out.println("Producer: Waiting for signal..."); while (!ready) { lock.wait(); } System.out.println("Producer: Received signal, proceeding."); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }); Thread consumer = new Thread(() -> { synchronized (lock) { System.out.println("Consumer: Sending signal."); ready = true; lock.notify(); } }); producer.start(); Thread.sleep(1000); // Ensure producer waits first consumer.start(); producer.join(); consumer.join(); } }
Output
Producer: Waiting for signal...
Consumer: Sending signal.
Producer: Received signal, proceeding.
Common Pitfalls
- Calling wait/notify outside synchronized block: Causes
IllegalMonitorStateException. - Using notify instead of notifyAll: Can cause some threads to wait forever if multiple threads wait on the same object.
- Not using a loop with wait: Threads should check the condition in a loop after waking up to avoid spurious wakeups.
java
/* Wrong way: wait called outside synchronized block */ // obj.wait(); // Throws IllegalMonitorStateException /* Right way: wait inside synchronized block with loop */ synchronized (obj) { while (!condition) { obj.wait(); } }
Quick Reference
| Method | Description | Usage Requirement |
|---|---|---|
| wait() | Pauses current thread until notified | Inside synchronized block on the object |
| notify() | Wakes one waiting thread | Inside synchronized block on the object |
| notifyAll() | Wakes all waiting threads | Inside synchronized block on the object |
Key Takeaways
Always call wait() and notify() inside a synchronized block on the same object.
Use a loop to check the waiting condition when calling wait() to handle spurious wakeups.
notify() wakes one waiting thread; notifyAll() wakes all waiting threads.
Calling wait() releases the object's lock until notified.
Avoid calling wait() or notify() outside synchronized blocks to prevent exceptions.