Java Reference
In-Depth Information
reads each value produced once and only once, the total will be 55. However, if you exe-
cute this program several times, you'll see that the total is not always 55 (as shown in the
outputs in Fig. 23.13). To emphasize the point, the producer and consumer threads in the
example each sleep for random intervals of up to three seconds between performing their
tasks. Thus, we do not know when the producer thread will attempt to write a new value,
or when the consumer thread will attempt to read a value.
Interface
Buffer
The program consists of interface
Buffer
(Fig. 23.9) and classes
Producer
(Fig. 23.10),
Consumer
(Fig. 23.11),
UnsynchronizedBuffer
(Fig. 23.12) and
SharedBufferTest
(Fig. 23.13). Interface
Buffer
(Fig. 23.9) declares methods
blockingPut
(line 6) and
blockingGet
(line 9) that a
Buffer
(such as
UnsynchronizedBuffer
) must implement to
enable the
Producer
thread to place a value in the
Buffer
and the
Consumer
thread to re-
trieve a value from the
Buffer
, respectively. In subsequent examples, methods
blocking-
Put
and
blockingGet
will call methods that throw
InterruptedException
s—typically
this indicates that a method temporarily could be blocked from performing a task. We de-
clare each method with a
throws
clause here so that we don't have to modify this interface
for the later examples.
1
// Fig. 23.9: Buffer.java
2
// Buffer interface specifies methods called by Producer and Consumer.
3
public
interface
Buffer
4
{
5
// place int value into Buffer
6
public
void
blockingPut(
int
value)
throws
InterruptedException;
7
8
// return int value from Buffer
9
public
int
blockingGet()
throws
InterruptedException;
10
}
// end interface Buffer
Fig. 23.9
|
Buffer interface specifies methods called by
Producer
and
Consumer
. (
Caution:
The example of Figs. 23.9-23.13 is
not
thread safe.)
Class
Producer
Class
Producer
(Fig. 23.10) implements the
Runnable
interface, allowing it to be executed
as a task in a separate thread. The constructor (lines 11-14) initializes the
Buffer
reference
sharedLocation
with an object created in
main
(line 15 of Fig. 23.13) and passed to the con-
structor. As we'll see, this is an
UnsynchronizedBuffer
object that implements interface
Buffer
without synchronizing access to the shared object
. The
Producer
thread in this program
executes the tasks specified in the method
run
(Fig. 23.10, lines 17-39). Each iteration of
the loop (lines 21-35) invokes
Thread
method
sleep
(line 25) to place the
Producer
thread
into the
timed waiting
state for a random time interval between 0 and 3 seconds. When the
thread awakens, line 26 passes the value of control variable
count
to the
Buffer
object's
blockingPut
method to set the shared buffer's value. Lines 27-28 keep a total of all the val-
ues produced so far and output that value. When the loop completes, lines 36-37 display a
message indicating that the
Producer
has finished producing data and is terminating. Next,
method
run
terminates, which indicates that the
Producer
completed its task. Any method
called from a
Runnable
's
run
method (e.g.,
Buffer
method
blockingPut
) executes as part