The wait() and notify() methods are used for inter-thread communication in Java. They allow one thread to pause its execution until another thread signals that a specific condition has been met. These methods are commonly used when threads need to coordinate access to shared resources.
Key Points: • wait() causes a thread to release the lock and enter the waiting state. • notify() wakes up one waiting thread, while notifyAll() wakes up all waiting threads. • Both methods must be called within a synchronized block or method. • They are commonly used in Producer-Consumer scenarios. • wait() and notify() help avoid busy waiting and improve resource utilization.
Why Do We Need wait() and notify()?
Consider two threads:
Producer Thread:
• Generates data.
Consumer Thread:
• Processes data.
Problem:
The consumer should wait if no data is available.
Solution:
• Consumer calls wait(). • Producer adds data and calls notify(). • Consumer wakes up and continues processing.
This enables efficient communication between threads.
Common Scenario: Producer-Consumer Problem
Producer:
Produces items and stores them in a shared buffer.
Consumer:
Consumes items from the buffer.
If the buffer is empty:
Consumer waits.
When the producer adds an item:
Producer notifies the consumer.
Flow:
Consumer | Buffer Empty | wait() | Waiting State | Producer Adds Data | notify() | Consumer Resumes
Code Example:
class SharedResource {
private boolean available =
false;
public synchronized void produce() {
available = true;
System.out.println(
"Data Produced");
notify();
}
public synchronized void consume()
throws InterruptedException {
while (!available) {
wait();
}
System.out.println(
"Data Consumed");
available = false;
}
}
public class Demo {
public static void main(String[] args) {
SharedResource resource =
new SharedResource();
Thread consumer =
new Thread(() -> {
try {
resource.consume();
} catch (InterruptedException e) {
Thread.currentThread()
.interrupt();
}
});
Thread producer =
new Thread(resource::produce);
consumer.start();
producer.start();
}
}Possible Output:
Data Produced
Data Consumed
How wait() Works
When a thread executes:
wait();
It:
• Releases the object's monitor lock. • Moves to the Waiting state. • Remains suspended until notified.
Thread State:
RUNNING | wait() | WAITING | notify() | RUNNABLE
How notify() Works
When a thread executes:
notify();
It:
• Wakes up one waiting thread. • Does not immediately release the lock. • The awakened thread must wait until the lock becomes available.
notifyAll()
notifyAll();Wakes up all waiting threads.
Use when:
• Multiple threads are waiting. • Any waiting thread may proceed.
Real-World Example
Online Food Ordering System
Thread 1:
Customer places an order.
Thread 2:
Restaurant waits for orders.
If no orders exist:
Restaurant thread calls wait().
When a customer places an order:
Customer thread calls notify().
Restaurant thread wakes up and processes the order.
Important Rules
1. wait(), notify(), and notifyAll() belong to the Object class. 2. They must be called from synchronized blocks or methods. 3. Calling them without synchronization causes IllegalMonitorStateException. 4. Use a loop instead of an if condition when checking the waiting condition.
Recommended:
while (!condition) {
wait();
}Instead of:
if (!condition) {
wait();
}Interview Tip: A concise interview answer is:
"A common use case for wait() and notify() is the Producer-Consumer problem. If a consumer thread tries to consume data that is not yet available, it calls wait() and releases the lock. Once the producer creates the data, it calls notify() to wake the waiting consumer. This allows efficient inter-thread communication without continuous polling or unnecessary CPU usage."