Java wait & notify
In this page:
synchronized (lockObject) {
while (!condition) {
lockObject.wait();
}
lockObject.notify(); // or notifyAll()
}
Inter-Thread Communication
Inter-thread communication lets synchronized threads coordinate their work and exchange signals using three methods inherited from the Object class: wait(), notify(), and notifyAll(). These let threads pause until conditions elsewhere in the program change, rather than wastefully polling in a loop.
Example: Inter-Thread Communication
// Define the class Main
public class Main {
// Program entry point: the JVM starts running here
public static void main(String[] args) throws InterruptedException {
// Create a new Object object and store it in monitor
Object monitor = new Object();
// synchronized lets only one thread run this code at a time
synchronized (monitor) {
// Print a line to the console
System.out.println("wait()/notify()/notifyAll() coordinate threads via this monitor");
}
}
}
Login to try C/C++/Java/PHP code in the editor
The wait() Method
Calling wait() inside a synchronized block immediately pauses the calling thread and, crucially, releases the monitor lock it was holding, letting other threads acquire that same lock and make progress. The waiting thread stays paused until some other thread calls notify() or notifyAll() on that same object.
Example: The wait() Method
public class Main {
public static void main(String[] args) throws InterruptedException {
final Object lock = new Object();
Thread waiter = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("Waiting...");
lock.wait(200); // releases the lock while paused
System.out.println("Resumed");
} catch (InterruptedException e) {}
}
});
waiter.start();
waiter.join();
}
}
Login to try C/C++/Java/PHP code in the editor
The notify() Method
The notify() method wakes up a single, arbitrarily chosen thread that's currently waiting on the object's monitor lock. It must be called from inside a synchronized block on that same object, and if multiple threads are waiting, there's no guarantee which one gets picked.
Example: The notify() Method
// Define the class Main
public class Main {
// Program entry point: the JVM starts running here
public static void main(String[] args) throws InterruptedException {
// Create a new Object object and store it in lock
final Object lock = new Object();
// Create a new Thread object and store it in waiter
Thread waiter = new Thread(() -> {
// synchronized lets only one thread run this code at a time
synchronized (lock) {
// Try code that might throw an exception
try { lock.wait(); } catch (InterruptedException e) {}
// Print a line to the console
System.out.println("Woken by notify()");
}
});
// Start the thread; it runs in parallel with this code
waiter.start();
Thread.sleep(100);
synchronized (lock) { lock.notify(); }
waiter.join();
}
}
Login to try C/C++/Java/PHP code in the editor
The notifyAll() Method
The notifyAll() method wakes up every thread currently waiting on the object's monitor, rather than just one. This is generally the safer choice over notify() when multiple threads might be waiting for different conditions, since notify() alone could accidentally wake the wrong one.
Example: The notifyAll() Method
public class Main {
public static void main(String[] args) throws InterruptedException {
final Object lock = new Object();
Runnable waitTask = () -> {
synchronized (lock) {
try { lock.wait(); } catch (InterruptedException e) {}
System.out.println(Thread.currentThread().getName() + " woken");
}
};
Thread t1 = new Thread(waitTask), t2 = new Thread(waitTask);
t1.start(); t2.start();
Thread.sleep(100);
synchronized (lock) { lock.notifyAll(); } // wakes both, not just one
t1.join(); t2.join();
}
}
Login to try C/C++/Java/PHP code in the editor
Producer-Consumer Simulation
The classic producer-consumer pattern uses wait() and notify() to coordinate a shared, bounded buffer: the producer calls wait() when the buffer is full, and the consumer calls wait() when it's empty, with each side calling notify() after changing the buffer's state to wake the other up.
Example: Producer-Consumer Simulation
// Import java.util.LinkedList so it can be used by its short name
import java.util.LinkedList;
// Define the class Main
public class Main {
// Create a new LinkedList object and store it in buffer
static final LinkedList<Integer> buffer = new LinkedList<>();
static final int CAPACITY = 1;
// Program entry point: the JVM starts running here
public static void main(String[] args) throws InterruptedException {
// Create a new Thread object and store it in producer
Thread producer = new Thread(() -> {
// synchronized lets only one thread run this code at a time
synchronized (buffer) {
while (buffer.size() == CAPACITY) { try { buffer.wait(); } catch (InterruptedException e) {} }
buffer.add(42);
// Print a line to the console
System.out.println("Produced 42");
buffer.notify();
}
});
Thread consumer = new Thread(() -> {
// synchronized lets only one thread run this code at a time
synchronized (buffer) {
while (buffer.isEmpty()) { try { buffer.wait(); } catch (InterruptedException e) {} }
System.out.println("Consumed " + buffer.poll());
}
});
producer.start(); producer.join();
consumer.start(); consumer.join();
}
}
Login to try C/C++/Java/PHP code in the editor
- Calling
wait()ornotify()outside asynchronizedblock on the same object, which throws anIllegalMonitorStateException. - Checking the condition with
ifinstead of awhileloop beforewait(), so a spurious wakeup or another thread can leave the condition false when the thread continues. - Calling
notify()before the other thread has calledwait(), so the signal is lost and the waiting thread sleeps forever.
Chapter Quiz — Complete all 8 topics to unlock
0/8 topics done
Complete these topics first: