Java Reference
In-Depth Information
• The simplest way to implement a bounded buffer is to use an
ArrayBlockingQueue
for the buffer
so that all of the synchronization details are handled for you.
Section 23.9 (Advanced) Producer/Consumer Relationship: The
Lock
and
Condition
Interfaces
•The
Lock
and
Condition
interfaces (p. 1002) give programmers more precise control over thread
synchronization, but are more complicated to use.
• Any object can contain a reference to an object that implements the
Lock
interface (of package
java.util.concurrent.locks
). A thread calls a
Lock
's
lock
method (p. 1002) to acquire the
lock. Once a
Lock
has been obtained by one thread, the
Lock
will not allow another thread to
obtain it until the first thread releases it (by calling the
Lock
's
unlock
method; p. 1002).
• If several threads are trying to call method
lock
on the same
Lock
object at the same time, only
one thread can obtain the lock—the others are placed in the
waiting
state. When a thread calls
unlock
, the object's lock is released and a waiting thread attempting to lock the object proceeds.
• Class
ReentrantLock
(p. 1002) is a basic implementation of the
Lock
interface.
•The
ReentrantLock
constructor takes a
boolean
that specifies whether the lock has a fairness pol-
icy (p. 1002). If
true
, the
ReentrantLock
's fairness policy is “the longest-waiting thread will ac-
quire the lock when it's available”—this prevents indefinite postponement. If the argument is set
to
false
, there's no guarantee as to which waiting thread will acquire the lock when it's available.
• If a thread that owns a
Lock
determines that it cannot continue with its task until some condition
is satisfied, the thread can wait on a condition object (p. 1003). Using
Lock
objects allows you to
explicitly declare the condition objects on which a thread may need to wait.
•
Condition
(p. 1003) objects are associated with a specific
Lock
and are created by calling
Lock
method
newCondition
, which returns a
Condition
object. To wait on a
Condition
, the thread
can call the
Condition
's
await
method. This immediately releases the associated
Lock
and places
the thread in the
waiting
state for that
Condition
. Other threads can then try to obtain the
Lock
.
•When a
runnable
thread completes a task and determines that a
waiting
thread can now continue,
the
runnable
thread can call
Condition
method
signal
to allow a thread in that
Condition
's
wait-
ing
state to return to the
runnable
state. At this point, the thread that transitioned from the
wait-
ing
state to the
runnable
state can attempt to reacquire the
Lock
.
• If multiple threads are in a
Condition
's
waiting
state when
signal
is called, the default imple-
mentation of
Condition
signals the longest-waiting thread to transition to the
runnable
state.
• If a thread calls
Condition
method
signalAll
, then all the threads waiting for that condition
transition to the
runnable
state and become eligible to reacquire the
Lock
.
• When a thread is finished with a shared object, it must call method
unlock
to release the
Lock
.
•
Lock
s allow you to interrupt waiting threads or to specify a timeout for waiting to acquire a
lock—not possible with
synchronized
. Also, a
Lock
object is not constrained to be acquired and
released in the same block of code, which is the case with the
synchronized
keyword.
•
Condition
objects allow you to specify multiple conditions on which threads may wait. Thus, it's
possible to indicate to waiting threads that a specific condition object is now true by calling that
Condition
object's
signal
or
signallAll
methods (p. 1003). With
synchronized
, there's no way
to explicitly state the condition on which threads are waiting.
Section 23.11 Multithreading with GUI:
SwingWorker
• The event dispatch thread (p. 1011) handles interactions with the application's GUI compo-
nents. All tasks that interact with the GUI are placed in an event queue and executed sequentially
by this thread.