Java Reference
In-Depth Information
reacquire the lock
. Method
notifyAll
returns immediately, then method
blockingGet
returns the value of
buffer
to its caller. When method
blockingGet
returns, the lock on
the
SynchronizedBuffer
object is
implicitly released
.
Error-Prevention Tip 23.3
Always invoke method
wait
in a loop that tests the condition the task is waiting on. It's
possible that a thread will reenter the
runnable
state (via a timed wait or another thread
calling
notifyAll
) before the condition is satisfied. Testing the condition again ensures
that the thread will not erroneously execute if it was notified early.
Method
displayState
Is Also
synchronized
Notice that method
displayState
is a
synchronized
method. This is important because
it, too, reads the
SynchronizedBuffer
's shared mutable data. Though only one thread at
a time may acquire a given object's lock, one thread may acquire the same object's lock
multiple
times—this is known as a
reentrant lock
and enables one
synchronized
method
to invoke another on the same object.
Testing Class
SynchronizedBuffer
Class
SharedBufferTest2
(Fig. 23.17) is similar to class
SharedBufferTest
(Fig. 23.13).
SharedBufferTest2
contains method
main
(Fig. 23.17, lines 9-26), which launches the
application. Line 12 creates an
ExecutorService
to run the
Producer
and
Consumer
tasks.
Line 15 creates a
SynchronizedBuffer
object and assigns its reference to
Buffer
variable
sharedLocation
. This object stores the data that will be shared between the
Producer
and
Consumer
. Lines 17-18 display the column heads for the output. Lines 21-22 execute a
Producer
and a
Consumer
. Finally, line 24 calls method
shutdown
to end the application
when the
Producer
and
Consumer
complete their tasks and line 25 waits for the scheduled
tasks to complete. When method
main
ends (line 26), the main thread of execution termi-
nates.
1
// Fig. 23.17: SharedBufferTest2.java
2
// Two threads correctly manipulating a synchronized buffer.
3
import
java.util.concurrent.ExecutorService;
4
import
java.util.concurrent.Executors;
5
import
java.util.concurrent.TimeUnit;
6
7
public
class
SharedBufferTest2
8
{
9
public
static
void
main(String[] args)
throws
InterruptedException
10
{
11
// create a newCachedThreadPool
12
ExecutorService executorService = Executors.newCachedThreadPool();
13
14
// create SynchronizedBuffer to store ints
Buffer sharedLocation =
new
SynchronizedBuffer();
15
16
17
System.out.printf(
"%-40s%s\t\t%s%n%-40s%s%n%n"
,
"Operation"
,
18
"Buffer"
,
"Occupied"
,
"---------"
,
"------\t\t--------"
);
19
Fig. 23.17
|
Two threads correctly manipulating a synchronized buffer. (Part 1 of 3.)