The get() and put() methods in the CubbyHole object both make use of the notify() and wait() methods to coordinate getting and putting values into the CubbyHole. Both notify() and wait() are members of the java.lang.Object class.
The notify() and wait() methods can only be called from a synchronized method.
The notify() method
The get() method calls notify() as the last thing it does (besides return). The notify() method chooses one thread that is waiting on the monitor held by the current thread and wakes it up. Typically, the waiting thread will grab the monitor and proceed.
In the case of the Producer/Consumer example, the Consumer thread calls the get() method, so the Consumer thread holds the monitor for the CubbyHole during the execution of get(). At the end of the get() method, the call to notify() wakes up the Producer thread which is waiting on the CubbyHole's monitor. Now, the Producer thread can get the CubbyHole monitor and proceed.
public synchronized int get(){
while (available == false) {
try {
wait();
} catch (InterruptedException e) {
}
}
available = false;
notify(); // notifies Producer
return seq;
}
If multiple threads were waiting for the CubbyHole monitor, the Java runtime system chooses one of the waiting threads, and makes no commitments or guarantees about which thread will be chosen.
The put() method works in a similar fashion waking up the Consumer thread that is waiting for the Producer to release the monitor.
The Object class has another method--notifyAll()--that wakes up all the threads waiting on the same monitor. In this situation, the awakened threads compete for the monitor. One thread gets the monitor and the others go back to waiting.
The wait() method
The wait() method causes the current thread to wait (possibly forever) until another thread notifies it of a condition change. You use wait() in conjunction with notify() to coordinate the activities of multiple threads using the same resources.
The get() contains a while statement that loops until available becomes true. If available is false, then the Consumer knows that the Producer has not yet produced a new number and the Consumer should wait until it has.
The while loop contains the call to wait(). The wait() method waits indefinitely for a notification from the Producer thread. When the put() method calls notify(), the Consumer wakes up from the wait state and continues within the while loop. Presumably, the Producer has generated a new number and the get() method drops out of the while loop and proceeds. If the Prodcuer had not generated a number, get() would go back to the beginning of the loop and continue to wait until the Producer had generated a new number and called notify().
public synchronized int get() {
while (available == false) {
try {
wait(); // waits for notify() call from Producer
} catch (InterruptedException e) {
}
}
available = false;
notify();
return seq;
}
The put() method works in a similar fashion waiting for the Consumer thread to consume the current value before allowing the Producer to produce a new one.
Besides the version used in the Producer/Consumer example which waits indefinitely for notification, the Object class contains two other versions of the wait() method:
wait(long timeout)
waits for notification or until the timeout period has elapsed--timeout is measured in milliseconds.
wait(long timeout, int nanos)
waits for notification or until the timeout period plus the additional nanoseconds has elapsed.
0 comments:
Post a Comment