Creating and Starting Threads in Java
A thread is alive from the time it is started until it terminates, and a dead thread cannot be restarted; isAlive() tests whether a thread has terminated.
A Background Download and the Main Thread
Imagine a program in which a background thread downloads a file while the main thread keeps the user interface responsive. At some point the main thread needs to know whether the download is finished. It cannot simply assume the answer, and it cannot reach into the other thread and read its progress directly. Java provides a small set of methods on the Thread class that let one thread observe, pause, and signal another.
This article follows those methods through one question at a time: how to ask whether a thread is still going, how to pause a thread, how to send it a signal, and how the receiving thread notices that signal. Along the way, you will trace a single thread through its states, because the rules for these methods depend on which state the thread is in.
Following a Thread from Start to Death
A thread is alive from the time it is started until it terminates. Once it terminates, it is called dead. A dead thread cannot be restarted.
A thread becomes alive at the moment it is started, and it stays alive until it terminates. Terminating happens when the run() method ends for some reason. The same idea is sometimes described as killing or aborting a thread. Whichever word you use, the important point is the same: a thread that has terminated cannot be restarted.
Being alive does not mean the thread is always running on the processor. A thread that has been started may be running, or it may be sleeping. A sleeping thread is still alive but not running. Sleeping is one of the pauses the Thread class offers, and it is covered later in this article.
What do you think happens?
A thread has been started and is currently sleeping inside sleep(). Is it alive, or is it dead?
Reveal answer
Alive, because it has been started and has not terminated
A sleeping thread is still alive but not running. Dead only applies after the thread has terminated, which happens when its run() method ends.
The diagram traces the transitions. Calling start() moves the thread from not yet started into the alive state. Calling sleep() moves it into alive-but-sleeping. A sleeping thread can wake, either after its pause or early when an interrupt arrives. When the run() method finally ends, the thread becomes dead, and no further start() can bring it back.
Checking Whether a Thread Has Finished
Sometimes one thread needs to know whether another has finished. For this purpose a Thread object provides the method isAlive(). If thrd is a Thread, then thrd.isAlive() is a boolean-valued method that tests whether thrd has terminated. It answers a yes-or-no question about the thread it is called on, which makes it a natural tool for a waiting or monitoring thread.
public class AliveDemo {
public static void main(String[] args) throws InterruptedException {
Thread worker = new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// worker was not interrupted in this example
}
});
worker.start();
System.out.println(worker.isAlive());
Thread.sleep(2000);
System.out.println(worker.isAlive());
}
}- 1Line 3 creates a Thread object whose
run()method sleeps for one second. - 2Line 9 starts the worker, which moves it into the alive state.
- 3Line 10 asks
isAlive()and gets true because the worker has not terminated. - 4Line 11 pauses the main thread so the worker has time to finish.
- 5Line 12 asks
isAlive()again and gets false because the worker has terminated.
- The worker thread is started, so it becomes alive.
- The first
isAlive()call happens while the worker is still sleeping, so it reports true. - The main thread then waits 2000 milliseconds, longer than the worker's 1000-millisecond pause.
- By then the worker's
run()method has ended and the worker is dead, soisAlive()reports false.
true
falseWhy a Dead Thread Stays Dead
A common assumption is that a Thread object can be reused for another run after it finishes. The source is clear that it cannot. A terminated thread is dead, and a dead thread cannot be restarted. If you want the work to happen again, you create a new Thread object and start that one.
| Situation | Dead Thread object | Newly created Thread object |
|---|---|---|
| Current state | Terminated, because its run() method has ended | Not yet started, so not alive |
| Can start() bring it back to life? | No, a dead thread cannot be restarted | Yes, start() makes it alive for the first time |
| What to do to run the work again | Create a new Thread object instead | Call start() on this object |
| Result of isAlive() right after start() | Not applicable, because the thread cannot be restarted | Reports true while the thread has not yet terminated |
Reusing a Thread object is not an option once it is dead. A new Thread object is the way to run the work again.
Pausing a Thread with sleep()
Signalling a Sleeping Thread with interrupt()
Sometimes one thread needs to wake up another thread that is sleeping, or that has paused for some other reason. For this, you call thrd.interrupt() on the Thread object that should be interrupted. The method is a convenient way to send a signal from one thread to another. The receiving thread is not forced to stop. It is simply told that something has happened, and how it responds is up to the code in its catch handler.
The diagram shows the exchange in order. The main thread sends the signal with interrupt(). The sleeping worker does not learn about it through any special mechanism other than the exception. The InterruptedException is thrown, control moves into the catch handler, and the worker's own code decides what to do next.
public class InterruptDemo {
public static void main(String[] args) throws InterruptedException {
Thread worker = new Thread(() -> {
try {
Thread.sleep(5000);
System.out.println("Finished sleeping");
} catch (InterruptedException e) {
System.out.println("Interrupted while sleeping");
}
});
worker.start();
Thread.sleep(500);
worker.interrupt();
}
}- 1Lines 3 to 11 define the worker, whose sleep is wrapped in a try..catch.
- 2Line 12 starts the worker, which moves it into the alive state and begins its sleep.
- 3Line 13 pauses the main thread for half a second, so the worker is already sleeping.
- 4Line 14 calls
interrupt()on the worker, which signals it. - 5The worker's sleep throws
InterruptedException, and control moves into the catch block, which prints a message and ends therun()method.
- The worker is set to sleep for five seconds.
- The main thread waits briefly, then calls
interrupt()on the worker. - The worker's catch block handles the signal rather than being forced to stop.
Checking the Flag with Thread.interrupted()
The catch handler is not the only place a thread can discover an interrupt. Outside any catch handler, a thread can ask whether it has been interrupted by calling the static method Thread.interrupted(). This method tells whether the current thread, meaning the thread that executes the call, has been interrupted. It is a question about the thread that is asking, not about some other thread.
Thread.interrupted() has an unusual property: it clears the interrupted status when it answers. After one call, the status is reset, so a second call reports false unless another interrupt has arrived in between. This is why the check gives you only one chance to see the interruption. If you need the answer more than once, save the result in a variable.
Two checks after one interrupt
A thread has been interrupted, so its interrupted status is set. The thread calls Thread.interrupted() twice in a row, with no other interrupt arriving between the calls. What does each call return?
- 1First call
The status is set, so the call reports true. Because the call clears the status as it answers, the status is now reset.
- 2Second call
The status was cleared by the first call, and no new interrupt has arrived, so this call reports false.
- 3Saving the result
If the code needed the true answer later, it should have stored the first result in a variable rather than calling
Thread.interrupted()a second time.
The first call returns true and the second returns false. Only the first call sees the interruption.
Mistakes Beginners Make with Thread States
Common mistake Trying to restart a thread by calling start() on the same dead Thread object
Why it failsA thread that has terminated cannot be restarted.
Do this insteadCreate a new Thread object and start that one to run the work again.
Common mistake Treating isAlive() true as proof that the thread is currently running
Why it failsA sleeping thread is still alive but not running, so the answer does not describe what the processor is doing.
Do this insteadRead isAlive() as only telling you whether the thread has terminated yet.
Common mistake Calling interrupt() and expecting the thread to stop immediately
Why it failsThe receiving thread is not forced to stop. It is simply told that something has happened.
Do this insteadWrite the catch handler, or the interrupted check, so the thread decides how to respond.
Common mistake Calling Thread.interrupted() twice and expecting true both times
Why it failsThe call clears the interrupted status when it answers, so the second call reports false unless another interrupt arrived.
Do this insteadStore the first result in a variable and test that variable as many times as needed.
Common mistake Wrapping sleep() in an empty catch block and losing the signal entirely
Practice: Predict the Thread States
A worker thread is started and then calls sleep(3000). One second later, the main thread calls interrupt() on the worker. Describe the worker's state before the interrupt, what happens at the moment of the interrupt, and whether the worker can be restarted afterward once its run() method has ended.
Hints
- Before the interrupt, the worker is alive but sleeping.
- The interrupt arrives as an
InterruptedExceptioninside the worker's sleep call. - Once
run()ends, the worker is dead, and a dead thread cannot be restarted.
Key Takeaways
- A thread is alive from the moment it is started until it terminates, and a dead thread cannot be restarted. A sleeping thread is still alive but not running.
isAlive()tests whether a thread has terminated, so it answers a yes-or-no question about one moment in time.Thread.sleep(milliseconds)pauses the calling thread, and itsInterruptedExceptionis checked, so it must be handled, usually with try..catch.interrupt()sends a signal to a sleeping or paused thread. The receiving thread learns of it through anInterruptedExceptionor by callingThread.interrupted(), and it decides how to respond.Thread.interrupted()checks the status of the current thread and clears it as it answers, so save the result if you need it more than once.