|
|
Start of Tutorial > Start of Trail > Start of Lesson |
Search
Feedback Form |
TheCubbyHolestores its value in a private member variable calledcontents.CubbyHolehas another private member variable,available, that is aboolean.availableistruewhen the value has just been put but not yet gotten and is false when the value has been gotten but not yet put. So, 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?getdoes nothing. Similarly, if theProducercallsputbefore theConsumergot the value,putdoesn't do anything.You really want the
Consumerto wait until theProducerputs something in theCubbyHoleand theProducermust notify theConsumerwhen it's done so. Similarly, theProducermust 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 implementations of
getandputthat wait on and notify each other of their activities:The code in thepublic synchronized int get() { while (available == false) { try { // wait for Producer to put value wait(); } catch (InterruptedException e) { } } available = false; // notify Producer that value has been retrieved notifyAll(); return contents; } public synchronized void put(int value) { while (available == true) { try { // wait for Consumer to get value wait(); } catch (InterruptedException e) { } } contents = value; available = true; // notify Consumer that 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. When theProducerputs something in theCubbyHole, it notifies theConsumerby callingnotifyAll. TheConsumerthen comes out of the wait state,availableis nowtrue, the loop exits, and thegetmethod returns the value in theCubbyHole.The
putmethod works in a similar fashion, waiting 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 the notify method, which arbitrarily wakes up one of the threads waiting on this object.The
Objectclass contains not only the version ofwaitthat is used in the producer/consumer example and which waits indefinitely for notification, but also two other versions of thewaitmethod:
- 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, but you can easily wake upwaitwith a notify 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-2004 Sun Microsystems, Inc. All rights reserved.