Java Reference
In-Depth Information
The following sequence of events occurs when the code executes:
1. Assuming the Consumer thread runs first (which is only an assumption and not a guar-
antee), its run method is invoked.
2. On line 10, the thread attempts to acquire the monitor lock of the stack. Again, let's
assume the lock is available.
3. The Consumer pops an int off the stack. With our assumptions so far, the value
returned is -1 because the Producer has not had a chance to push anything onto the
stack yet.
4. The Consumer calls wait on line 15 and gives up the monitor lock of the stack.
5. The Producer thread is started and its run method is invoked. A random int between
0 and 4 is pushed onto the stack on line 12.
6. On line 14, the Producer thread attempts to acquire the lock of the stack. This step is
necessary because the call to notify can only occur if the thread owns the lock on the
stack.
7. On line 16, the notify method awakens the Consumer thread and its state changes
from WAITING to BLOCKED . Notice the Consumer thread is not RUNNABLE at this point
in time. Why? Because the Producer thread still has the lock on the stack and the
Consumer thread was within synchronized code when it invoked wait .
8. The Producer thread gives up the lock of the MyStack2 object on line 17, causing the
Consumer thread to transition to the RUNNABLE state.
9. The Producer thread sleeps, allowing the Consumer thread to obtain the lock of the
stack and pop the recently pushed value. The stack is now empty because the Producer
is sleeping, so the Consumer waits again.
This process repeats indefi nitely because the threads run in infi nite while loops.
The output changes each time because we are dealing with threads and also because the
numbers pushed onto the stack are random. Here is a typical output of the code:
Waiting...
Just pushed 1
Notifying...
Just popped 1
Waiting...
Just pushed 3
Notifying...
Just popped 3
Waiting...
Just pushed 4
Notifying...
Just popped 4
Waiting...
Search WWH ::




Custom Search