of threads by developers is not desirable. Instead, the runtime should provide “fire
and forget” capabilities, whereby the program specifies what needs to be done, but
the low-level details of how this is to be accomplished are left to the runtime.
This viewpoint can be seen in the concurrency toolkit contained in java.util.con
current , a full discussion of which is outside the scope of this topic. The interested
reader should refer to Java Concurrency in Practice by Brian Goetz et al. (Addison-
For the remainder of this chapter, we will introduce the low-level concurrency
mechanisms that the Java platform provides, and that every Java developer should
be aware of.
Let's start by looking at the lifecycle of an application thread. Every operating system
has a view of threads that can differ in the details (but in most cases is broadly simi‐
lar at a high level). Java tries hard to abstract these details away, and has an enum
called Thread.State —which wrappers over the operating system's view of the
thread's state. The values of Thread.State provide an overview of the lifecycle of a
NEW The thread has been created but its start() method has not yet been called. All
threads start in this state.
The thread is running or is available to run when the operating system sched‐
The thread is not running because it is waiting to acquire a lock so that it can
enter a synchronized method or block. We'll see more about synchronized
methods and blocks later in this section.
The thread is not running because it has called Object.wait() or
The thread is not running because it has called Thread.sleep() or has called
Object.wait() or Thread.join() with a timeout value.
The thread has completed execution. Its run() method has exited normally or
by throwing an exception.
These states represent the view of a thread that is common (at least across main‐
stream operating systems), leading to a view like that in Figure 6-4 .