A thread can undergo some states during its life cycle. It is because in a multithreaded environment when multiple threads are executing only one thread can use the CPU at a time, and all other threads should be in some other states either waiting for their turn for the CPU or waiting for some other condition to be satisfied.
A thread is always in one of five states: newborn, runnable, running, dead and blocked. Figure shows the life cycle of a thread.
We’ll be covering the following topics in this tutorial:
The newborn state
When a thread is called, it is in the newborn state, that is, when it has been created and is not yet running. In other words, a start () method has not been invoked on this thread. In this state, system resources are not yet allocated to the thread. When a thread is in the newborn state, calling any method other than start () method causes an IllegalThreadStateException.
The runnable state
A thread in the runnable state is ready for execution but is not being executed currently. Once a thread is in the runnable state, it gets all the resources of the system (as, for example, access to the CPU) and moves on to the running state.All runnable threads are in a queue and wait for CPU access. When the start () method is called on the newborn thread, it will be in the runnable state. It is not in the running state yet because system resources such as the CPU (which might be serving another thread at that point) are not available.
The running state
After the runnable state, if the thread gets CPU access, it moves into the running state. The thread will be in the running state unless one of the following things occur:
• It dies (that is, the run () method exits).
• It gets blocked to the input/output for some reason.
• It calls sleep ().
• It calls wait ().
• It calls yield ().
• It is preempted by a thread of higher priority.
• Its quantum (time slice) expires.
A thread with a higher priority than the running thread can preempt the running thread if any of the following situations arise:
• If the thread with the higher priority comes out of the sleeping state.
• The I/O completes for a thread with a higher priority waiting for that I/O.
• Either notify () or notifyAll () is called on a thread that called wait.
When a thread calls the wait () method it goes in the waiting state. To wake up this thread, some other running thread should notify it.
The dead state
A thread goes into the dead state in two ways:
• If its run () method exits.
• A stop () method is invoked.
The run () method exits when it finished execution naturally or throws an uncaught exception. The stop () method kills the thread. A thread in the dead state cannot be executed further.
The blocked state
A thread can enter the blocked state when one of the following five conditions occurs:
• When sleep () is called,
• When suspend () is called,
• When wait () is called,
• The thread calls an operation, (For example, during input/output, a thread will not return until the I/O operation completes.),
• The thread is waiting for monitor.
A thread in the blocked state waits for some action to happen so that it can get ready. That is, if the thread requires some of the I/O operation, it will enter into the blocked state by giving the access to the CPU to another thread. After completion of the I/O operations it will enter into the runnable state.
A thread must move out of a blocked state into the runnable (or running) state using the opposite of whatever phenomenon put it into the blocked state.
• If a thread has been put to sleep (), the specified timeout period must expire.
• If a thread has called wait (), then some other thread using the resource for which the first thread is waiting must call notify () or notifyAll ().
• If a thread is waiting for the completion of an input or output operation, then the operation must finish.
Manipulating threads
Table lists some of the methods used to manipulate threads.
In addition to the methods described in Table, there are some which need to be discussed briefly. They include the sleep (), suspend (), resume (), wait (), notify (), notifyAll () and yield () methods.
Table. Some methods that are provided in the Thread class to manipulate threads
Name of the method | Function |
getName() | returns name of the thread |
setPriority () | to set the priority of the thread |
getPriority () | returns the thread priority |
isAlive () | Determines whether the thread is still running or not; isAlive () returns true if the method is running, Runnable or blocked. It returns false if the method is a new thread or dead |
join () | wait for a thread to terminate |
run () | entry point for the thread |
start() | start a thread by calling its run method |
stop() | terminate the thread abruptly |
sleep ()
A thread being executed can invoke sleep () to block the thread for some time and free the CPU. This thread goes into the sleep (blocked) state for the specified amount of time, after which it moves to the runnable state. The sleep method has the following prototypes:
public static void sleep (long millisec) throws InterruptedException;
public static void sleep (long millisec, int nanosec) throws InterruptedException;
suspend () and resume ()
The Thread class has a method suspend () to stop the thread temporarily and a method resume () to restart it at the point at which it is halted. The resume () method must be called by some thread other than the suspended one. The suspend () method is not recommended in application programming.
Wait (), notify () and notifyAll ()
When a running thread calls wait (), it enters into a waiting (blocked) state for the particular object on which wait was called. A thread in the waiting state for an object becomes ready on a call to notify () issued by another thread associated with that object. All threads waiting for a given object become ready when receiving a call to notifyAll () from another thread associated with that object.
yield ()
Some CPU-intensive operations of one thread may prevent other threads from being executed. To prevent this from happening, the first one can allow other threads to execute by invoking the yield () method. This method allows another thread of the same priority to be run. The thread from which yield () is invoked moves from the running state to the runnable state.
The methods sleep () and yield () are static methods.