wait/notify and Condition
Make one thread wait for another to change state, without burning CPU in a spin loop.
Open this lesson in the learning hubKey points
wait()releases the monitor and parks the thread.notify()wakes one waiter,notifyAll()wakes them all.- You must already hold the monitor to call them, or you get
IllegalMonitorStateException. - Always wait inside a
whileloop, never anif. Spurious wakeups are legal, and another thread may grab the state first. - Prefer
notifyAll()unless you can prove every waiter wants the same thing.notify()can wake the wrong one and stall. Conditionis theLockequivalent:await()andsignal(). One lock can carry several conditions, like notFull and notEmpty.- Both are low-level plumbing. Try
BlockingQueue, a latch or a future before writing your own.
Example
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Main {
public static void main(String[] args) throws InterruptedException {
Object monitor = new Object();
boolean[] ready = { false };
Thread waiter = new Thread(() -> {
synchronized (monitor) {
while (!ready[0]) { // ALWAYS a while loop, never an if
try { monitor.wait(); } catch (InterruptedException e) { return; }
}
System.out.println("wait/notify : woke up, condition is true");
}
});
waiter.start();
Thread.sleep(50);
synchronized (monitor) { ready[0] = true; monitor.notifyAll(); }
waiter.join();
Box box = new Box();
Thread consumer = new Thread(() -> {
try { System.out.println("condition : took " + box.take()); }
catch (InterruptedException e) { Thread.currentThread().interrupt(); }
});
consumer.start();
Thread.sleep(50);
box.put("apple");
consumer.join();
}
static class Box {
private final ReentrantLock lock = new ReentrantLock();
private final Condition notEmpty = lock.newCondition();
private final Queue<String> items = new ArrayDeque<>();
void put(String item) {
lock.lock();
try { items.add(item); notEmpty.signal(); } finally { lock.unlock(); }
}
String take() throws InterruptedException {
lock.lock();
try {
while (items.isEmpty()) notEmpty.await();
return items.remove();
} finally { lock.unlock(); }
}
}
}
Wait in a while loop, or you will eventually ship a very strange bug.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Multithreading course, and every lesson in it is listed on the Multithreading contents page.