Java Reference
In-Depth Information
so that they can remain constant while the precondition is tested. But if the precondition does
not hold, the lock must be released so another thread can modify the object state—otherwise
the precondition will never become true. The lock must then be reacquired before testing the
precondition again.
Listing 14.1. Structure of Blocking State-dependent Actions.
Bounded buffers such as
ArrayBlockingQueue
are commonly used in producer-con-
sumer designs. A bounded buffer provides
put
and
take
operations, each of which has pre-
conditions: you cannot take an element from an empty buffer, nor put an element into a full
buffer. State dependent operations can deal with precondition failure by throwing an excep-
tion or returning an error status (making it the caller's problem), or by blocking until the ob-
ject transitions to the right state.
We're going to develop several implementations of a bounded buffer that take different ap-
(
buf
,
head
,
tail
, and
count
) are guarded by the buffer's intrinsic lock. It provides syn-
chronized
doPut
and
doTake
methods that are used by subclasses to implement the
put
and
take
operations; the underlying state is hidden from the subclasses.
14.1.1. Example: Propagating Precondition Failure to Callers
GrumpyBoundedBuffer
in
Listing 14.3
is a crude first attempt at implementing a
bounded buffer. The
put
and
take
methods are
synchronized
to ensure exclusive ac-
cess to the buffer state, since both employ check-then-act logic in accessing the buffer.