Java Reference
In-Depth Information
complete or when the specified timeout elapses. If all tasks complete before the timeout elapses,
the method returns
true
; otherwise, it returns
false
.
• You can simulate atomicity (p. 974) by ensuring that only one thread performs a set of operations
at a time. Atomicity can be achieved with synchronized statements or synchronized methods.
• When you share immutable data across threads, you should declare the corresponding data fields
final
to indicate that variables' values will not change after they're initialized.
Section 23.5 Producer/Consumer Relationship without Synchronization
• In a multithreaded producer/consumer relationship (p. 976), a producer thread generates data
and places it in a shared object called a buffer. A consumer thread reads data from the buffer.
• Operations on a buffer data shared by a producer and a consumer should proceed only if the buf-
fer is in the correct state. If the buffer is not full, the producer may produce; if the buffer is not
empty, the consumer may consume. If the buffer is full when the producer attempts to write into
it, the producer must wait until there's space. If the buffer is empty or the previous value was
already read, the consumer must wait for new data to become available.
Section 23.6 Producer/Consumer Relationship:
ArrayBlockingQueue
•
ArrayBlockingQueue
(p. 984) is a fully implemented buffer class from package
java.util.con-
current
that implements the
BlockingQueue
interface.
•An
ArrayBlockingQueue
can implement a shared buffer in a producer/consumer relationship.
Method
put
(p. 984) places an element at the end of the
BlockingQueue
, waiting if the queue is
full. Method
take
(p. 984) removes an element from the head of the
BlockingQueue
, waiting if
the queue is empty.
•
ArrayBlockingQueue
stores shared mutable data in an array that's sized with an argument passed
to the constructor. Once created, an
ArrayBlockingQueue
is fixed in size.
Section 23.7 (Advanced) Producer/Consumer Relationship with
synchronized
,
wait
,
notify
and
notifyAll
• You can implement a shared buffer yourself using the
synchronized
keyword and
Object
meth-
ods
wait
,
notify
and
notifyAll
(p. 988).
• A thread can call
Object
method
wait
to release an object's monitor lock, and wait in the
waiting
state while the other threads try to enter the object's
synchronized
statement(s) or method(s).
• When a thread executing a
synchronized
statement (or method) completes or satisfies the con-
dition on which another thread may be waiting, it can call
Object
method
notify
(p. 988) to
allow a waiting thread to transition to the
runnable
state. At this point, the thread that was tran-
sitioned can attempt to reacquire the monitor lock on the object.
• If a thread calls
notifyAll
(p. 988), then all the threads waiting for the monitor lock become
eligible to reacquire the lock (that is, they all transition to the
runnable
state).
Section 23.8 (Advanced) Producer/Consumer Relationship: Bounded Buffers
• You cannot make assumptions about the relative speeds of concurrent threads.
• A bounded buffer (p. 995) can be used to minimize the amount of waiting time for threads that
share resources and operate at the same average speeds. If the producer temporarily produces val-
ues faster than the consumer can consume them, the producer can write additional values into
the extra buffer space (if any are available). If the consumer consumes faster than the producer
produces new values, the consumer can read additional values (if there are any) from the buffer.
• The key to using a bounded buffer with a producer and consumer that operate at about the same
speed is to provide the buffer with enough locations to handle the anticipated “extra” production.