Thread States: Life Cycle of a Thread
Thread States Life Cycle of a Thread
At any time, a thread is said to be in one of several thread states that are illustrated in the UML state diagram in Fig. 23.1. A few of the terms in the diagram are defined in later sections.
Figure 23.1. Thread life-cycle UML state diagram.
A new thread begins its life cycle in the new state. It remains in this state until the program starts the thread, which places the thread in the runnable state. A thread in this state is considered to be executing its task.
Sometimes a thread transitions to the waiting state while the thread waits for another thread to perform a task. Once in this state, a thread transitions back to the runnable state only when another thread signals the waiting thread to continue executing.
A runnable thread can enter the timed waiting state for a specified interval of time. A thread in this state transitions back to the runnable state when that time interval expires or when the event it is waiting for occurs. Timed waiting threads cannot use a processor, even if one is available. A thread can transition to the timed waiting state if it provides an optional wait interval when it is waiting for another thread to perform a task. Such a thread will return to the runnable state when it is signaled by another thread or when the timed interval expireswhichever comes first. Another way to place a thread in the timed waiting state is to put the thread to sleep. A sleeping thread remains in the timed waiting state for a designated period of time (called a sleep interval) at which point it returns to the runnable state. Threads sleep when they momentarily do not have work to perform. For example, a word processor may contain a thread that periodically writes a copy of the current document to disk for recovery purposes. If the thread did not sleep between successive backups, it would require a loop in which it continually tests whether it should write a copy of the document to disk. This loop would consume processor time without performing productive work, thus reducing system performance. In this case, it is more efficient for the thread to specify a sleep interval (equal to the period between successive backups) and enter the timed waiting state. This thread is returned to the runnable state when its sleep interval expires, at which point it writes a copy of the document to disk and reenters the timed waiting state.
A runnable thread enters the terminated state when it completes its task or otherwise terminates (perhaps due to an error condition). In the UML state diagram in Fig. 23.1, the terminated state is followed by the UML final state (the bull's-eye symbol) to indicate the end of the state transitions.
At the operating-system level, Java's runnable state actually encompasses two separate states (Fig. 23.2). The operating system hides these two states from the Java Virtual Machine (JVM), which only sees the runnable state. When a thread first transitions to the runnable state from the new state, the thread is in the ready state. A ready thread enters the running state (i.e., begins executing) when the operating system assigns the thread to a processoralso known as dispatching the thread. In most operating systems, each thread is given a small amount of processor timecalled a quantum or timeslicewith which to perform its task. When the thread's quantum expires, the thread returns to the ready state and the operating system assigns another thread to the processor (see Section 23.3). Transitions between these states are handled solely by the operating system. The JVM does not "see" these two statesit simply views a thread as being in the runnable state and leaves it up to the operating system to transition threads between the ready and running states. The process that an operating system uses to decide which thread to dispatch is known as thread scheduling and is dependent on thread priorities (discussed in the next section).
Figure 23.2. Operating system's internal view of Java's runnable state.