|      | Start of Tutorial > Start of Trail > Start of Lesson | Search Feedback Form | 
 
Let's investigate how the code inCubbyHole'sputandgetmethods helps theProducerand theConsumercoordinate their activities. TheCubbyHolestores its value in a private member variable calledcontents.CubbyHolehas another private member variable,available, a boolean. Theavailablevariable istruewhen the value has been put but not yet gotten and isfalsewhen the value has been gotten but not yet put. Here's one possible implementation for theputandgetmethods.As implemented, these two methods won't work. Look at thepublic synchronized int get() { //Won't work! if (available == true) { available = false; return contents; } } public synchronized void put(int value) { //Won't work! if (available == false) { available = true; contents = value; } }getmethod. What happens if theProducerhasn't put anything in theCubbyHoleandavailableisn'ttrue? Thegetmethod does nothing. Similarly, if theProducercalledputbefore theConsumergot the value,putdoesn't do anything.You really want the
Consumerto wait until theProducerputs something in theCubbyHoleand theProducernotifies theConsumerwhen it's done so. Similarly, theProducershould wait until theConsumertakes a value (and notifies theProducerof its activities) before replacing it with a new value. The two threads must coordinate more fully and can useObject'swaitandnotifyAllmethods to do so.The following new
getandputimplementations wait on and notify each other of their activities.The code in thepublic synchronized int get() { while (available == false) { try { //Wait forProducerto put value. wait(); } catch (InterruptedException e) { } } available = false; //NotifyProducerthat value has been retrieved. notifyAll(); return contents; } public synchronized void put(int value) { while (available == true) { try { //Wait forConsumerto get value. wait(); } catch (InterruptedException e) { } } contents = value; available = true; //NotifyConsumerthat value has been set. notifyAll(); }getmethod loops until theProducerhas produced a new value. Each time through the loop,getcalls thewaitmethod. Thewaitmethod relinquishes the lock on theCubbyHoleheld by theConsumer(thereby allowing theProducerto get the lock and update theCubbyHole) and then waits for notification from theProducer. When theProducerputs something in theCubbyHole, it notifiesConsumerby callingnotifyAll. TheConsumerthen comes out of thewaitstate and thegetmethod returns the value in theCubbyHole.The
putmethod works in a similar fashion. It waits for theConsumerthread to consume the current value before allowing theProducerto produce a new one.The
notifyAllmethod wakes up all threads waiting on the object in question (in this case, theCubbyHole). The awakened threads compete for the lock. One thread gets it, and the others go back to waiting. TheObjectclass also defines thenotifymethod, which arbitrarily wakes up one of the threads waiting on this object.The following are the three versions of the
waitmethod contained in theObjectclass:
wait(): waits indefinitely for notification. (This method was used in the producer-consumer example.)
wait(long timeout): waits for notification or until thetimeoutperiod has elapsed;timeoutis measured in milliseconds.
wait(long timeout, int nanos): waits for notification or untiltimeoutmilliseconds plusnanosnanoseconds have elapsed.
Note: Besides using these timedwaitmethods to synchronize threads, you also can use them in place ofsleep. Bothwaitandsleepdelay for the requested amount of time. You can easily wake upwaitwith anotify, but a sleeping thread cannot be awakened prematurely. This doesn't matter too much for threads that don't sleep for long, but it could be important for threads that sleep for minutes at a time.
 
|      | Start of Tutorial > Start of Trail > Start of Lesson | Search Feedback Form | 
Copyright 1995-2005 Sun Microsystems, Inc. All rights reserved.