Java Reference
In-Depth Information
• You cannot predict the order in which threads will be scheduled, even if you know the order in
which they were created and started.
• It's recommended that you use the
Executor
interface (p. 963) to manage the execution of
Run-
nable
objects. An
Executor
object typically creates and manages a group of threads—called a
thread pool (p. 963).
•
Executor
s (p. 964) can reuse existing threads and can improve performance by optimizing the
number of threads to ensure that the processor stays busy.
•
Executor
method
execute
(p. 963) receives a
Runnable
and assigns it to an available thread in a
thread pool. If there are none, the
Executor
creates a new thread or waits for one to become available.
• Interface
ExecutorService
(of package
java.util.concurrent
; p. 964) extends interface
Exec-
utor
and declares other methods for managing the life cycle of an
Executor
.
• An object that implements the
ExecutorService
interface can be created using
static
methods
declared in class
Executors
(of package
java.util.concurrent
).
•
Executors
method
newCachedThreadPool
(p. 965) returns an
ExecutorService
that creates new
threads as they're needed by the application.
•
ExecutorService
method
execute
executes its
Runnable
sometime in the future. The method re-
turns immediately from each invocation—the program does not wait for each task to finish.
• ExecutorService method shutdown (p. 967) notifies the ExecutorService to stop accepting new
tasks, but continues executing existing tasks and terminates when those tasks complete execution.
Section 23.4 Thread Synchronization
• Thread synchronization (p. 968) coordinates access to shared mutable data by multiple concur-
rent threads.
• By synchronizing threads, you can ensure that each thread accessing a shared object excludes all
other threads from doing so simultaneously—this is called mutual exclusion (p. 968).
• A common way to perform synchronization is to use Java's built-in monitors. Every object has a
monitor and a monitor lock (p. 968). The monitor ensures that its object's monitor lock is held
by a maximum of only one thread at any time, and thus can be used to enforce mutual exclusion.
• If an operation requires the executing thread to hold a lock while the operation is performed, a
thread must acquire the lock (p. 968) before it can proceed with the operation. Any other threads
attempting to perform an operation that requires the same lock will be
blocked
until the first
thread releases the lock, at which point the
blocked
threads may attempt to acquire the lock.
• To specify that a thread must hold a monitor lock to execute a block of code, the code should be
placed in a
synchronized
statement (p. 968). Such code is said to be guarded by the monitor lock.
•The
synchronized
statements are declared using the
synchronized
keyword:
synchronized
(
object
)
{
statements
}
// end synchronized statement
where
object
is the object whose monitor lock will be acquired;
object
is normally
this
if it's the
object in which the
synchronized
statement appears.
• Java also allows
synchronized
methods (p. 969). Before executing, a
synchronized
instance
method must acquire the lock on the object that's used to call the method. Similary, a
static
synchronized
method must acquire the lock on the class that's used to call the method.
•
ExecutorService
method
awaitTermination
(p. 973) forces a program to wait for threads to ter-
minate. It returns control to its caller either when all tasks executing in the
ExecutorService