Start of Tutorial > Start of Trail > Start of Lesson |
Search
Feedback Form |
Let's investigate how the code inCubbyHole
'sput
andget
methods helps theProducer
and theConsumer
coordinate their activities. TheCubbyHole
stores its value in a private member variable calledcontents
.CubbyHole
has another private member variable,available
, that is a boolean. Theavailable
variable istrue
when the value has been put but not yet gotten and isfalse
when the value has been gotten but not yet put. Here's one possible implementation for theput
andget
methods: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; } }get
method. What happens if theProducer
hasn't put anything in theCubbyHole
andavailable
isn'ttrue
? Theget
method does nothing. Similarly, if theProducer
calls put before theConsumer
got the value,put
doesn't do anything.You really want the
Consumer
to wait until theProducer
puts something in theCubbyHole
and theProducer
to notify theConsumer
when it's done so. Similarly, theProducer
should wait until theConsumer
takes a value (and notifies theProducer
of its activities) before replacing it with a new value. The two threads must coordinate more fully and can useObject
'swait
andnotifyAll
methods to do so.Here are the new
get
andput
implementations that wait on and notify each other of their activities:The code in thepublic synchronized int get() { while (available == false) { try { //wait forProducer
to put value wait(); } catch (InterruptedException e) { } } available = false; //notifyProducer
that value has been retrieved notifyAll(); return contents; } public synchronized void put(int value) { while (available == true) { try { //wait forConsumer
to get value wait(); } catch (InterruptedException e) { } } contents = value; available = true; //notifyConsumer
that value has been set notifyAll(); }get
method loops until theProducer
has produced a new value. Each time through the loop,get
calls thewait
method. Thewait
method relinquishes the lock held by theConsumer
on theCubbyHole
(thereby allowing theProducer
to get the lock and update theCubbyHole
) and then waits for notification from theProducer
. WhenProducer
puts something in theCubbyHole
, it notifiesConsumer
by callingnotifyAll
. TheConsumer
then comes out of the wait state and theget
method returns the value in theCubbyHole
.The
put
method works in a similar fashion. It waits for theConsumer
thread to consume the current value before allowing theProducer
to produce a new one.The
notifyAll
method 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. TheObject
class also defines thenotify
method, which arbitrarily wakes up one of the threads waiting on this object.There are the three versions of the
wait
method contained in theObject
class:
- wait()
- Waits indefinitely for notification. (This method was used in the producer-consumer example.)
- 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
timeout
milliseconds plusnanos
nanoseconds have elapsed.
Note: Besides using these timedwait
methods to synchronize threads, you also can use them in place ofsleep
. Bothwait
andsleep
delay for the requested amount of time. You can easily wake upwait
with 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.