|
|
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, that is 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 theProducercalls put before theConsumergot the value,putdoesn't do anything.You really want the
Consumerto wait until theProducerputs something in theCubbyHoleand theProducerto notify 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.Here are the new
getandputimplementations that 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 held by theConsumeron theCubbyHole(thereby allowing theProducerto get the lock and update theCubbyHole) and then waits for notification from theProducer. WhenProducerputs something in theCubbyHole, it notifiesConsumerby callingnotifyAll. TheConsumerthen comes out of the wait state 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.There 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 the
timeoutperiod has elapsed.timeoutis measured in milliseconds.
- wait(long timeout, int nanos)
- Waits for notification or until
timeoutmilliseconds 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 anotifybut 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.