A running thread may enter a waiting state by a wait(), sleep(), or join() call.
A running thread may enter a waiting state because it can't acquire the lock for a synchronized block of code.
wait(), notify(), and notifyAll() must be called from within a synchronized context!
Class Method Type Needs
Object try wait(optional timeout) catch instance synchronized,
Object notify() instance synchronized
Object notifyAll() instance synchronized
Main points to remember about wait():
The calling thread gives up the CPU.
The calling thread gives up the lock.
The calling thread goes into the monitor's waiting pool.
The thread that was notified must reacquire the monitor's lock before it can proceed.