The Java TM Tutorial

| Start of Tutorial > Start of Trail > Start of Lesson | Search

Trail: Essential Java Classes
Lesson: Doing Two or More Tasks At Once: Threads

## The Life Cycle of a Thread

> Now that you've seen how to give a thread something to do, we'll review some details that were glossed over in the previous section. In particular, we look at the life cycle of a thread: how to create and start a thread, some of the special things it can do while it's running, and how to stop it.

> The following diagram shows the states that a Java thread can be in during its life. It also illustrates which method calls cause a transition to another state. This figure is not a complete finite state diagram, but rather an overview of the more interesting and common facets of a thread's life. The remainder of this section uses the `Clock` applet previously introduced to discuss a thread's life cycle in terms of its state.

### Creating a Thread

> The application in which an applet is running calls the applet's `start` method when the user visits the applet's page. The `Clock` applet creates a `Thread`, `clockThread`, in its `start` with the bold code shown here:

> >     public void start() {
> >         if (clockThread == null) {
> >             clockThread = new Thread(this, "Clock");
> >             clockThread.start();
> >         }
> >     }

> After the bold statement has been executed, `clockThread` is in the New Thread state. When a thread is a New Thread, it is merely an empty `Thread` object; no system resources have been allocated for it yet. When a thread is in this state, you can only start the thread. Calling any method besides start when a thread is in this state makes no sense and causes an `IllegalThreadStateException`. (In fact, the runtime system throws an `IllegalThreadStateException` any time a method is called on a thread and that thread's state does not allow for that method call.)

> Notice that this--the `Clock` instance-- is the first argument to the thread constructor. The first argument to this thread constructor must implement the `Runnable` interface and becomes the thread's target. The clock thread gets its `run` method from its target `Runnable` object--in this case, the `Clock` instance. The second argument is just a name for the thread.

### Starting a Thread

> Now consider the next line of code in `Clock`'s `start` method shown here in bold:

> >     public void start() {
> >         if (clockThread == null) {
> >             clockThread = new Thread(this, "Clock");
> >             clockThread.start();
> >         }
> >     }

> The `start` method creates the system resources necessary to run the thread, schedules the thread to run, and calls the thread's `run` method. `ClockThread'`s `run` method is the one defined in the `Clock` class.

> After the `start` method has returned, the thread is "running". Yet, it's somewhat more complex than that. As the previous figure shows, a thread that has been started is actually in the Runnable state. Many computers have a single processor, thus making it impossible to run all "running" threads at the same time. The Java runtime system must implement a scheduling scheme that shares the processor between all "running" threads. (See Understanding Thread Priority for more information about scheduling.) So at any given time, a "running" thread actually may be waiting for its turn in the CPU.

> Here's another look at `Clock`'s `run` method:

> >     public void run() {
> >        Thread myThread = Thread.currentThread();
> >        while (clockThread == myThread) {
> >             repaint();
> >             try {
> >                 Thread.sleep(1000);
> >             } catch (InterruptedException e){
> >                 // the VM doesn't want us to sleep anymore,
> >                 // so get back to work
> >             }
> >         }
> >     }

> `Clock`'s `run` method loops while the condition `clockThread == myThread` is `true`. This exit condition is explained in more detail in Stopping a Thread. However, for now, know that it allows the thread, and thus the applet, to exit gracefully.

> Within the loop, the applet repaints itself and then tells the thread to sleep for one second (1000 milliseconds). An applet's `repaint` method ultimately calls the applet's `paint` method, which does the actual update of the applet's display area. The `Clock` `paint` method gets the current time, formats, and displays it:

> >     public void paint(Graphics g) {
> >         // get the time and convert it to a date
> >         Calendar cal = Calendar.getInstance();
> >         Date date = cal.getTime();
> >         // format it and display it
> >         DateFormat dateFormatter = DateFormat.getTimeInstance();
> >         g.drawString(dateFormatter.format(date), 5, 10);
> >     }

### Making a Thread Not Runnable

> A thread becomes Not Runnable when one of these events occurs:
> - Its `sleep` method is invoked.
> - The thread calls the `wait` method to wait for a specific condition to be satisifed.
> - The thread is blocking on I/O.
> The `clockThread` in the `Clock` applet becomes Not Runnable when the run method calls `sleep` on the current thread:

> >     public void run() {
> >         Thread myThread = Thread.currentThread();
> >         while (clockThread == myThread) {
> >             repaint();
> >             try {
> >                 Thread.sleep(1000);
> >             } catch (InterruptedException e){
> >                 // the VM doesn't want us to sleep anymore,
> >                 // so get back to work
> >             }
> >         }
> >     }

> During the second that the `clockThread` is asleep, the thread does not run, even if the processor becomes available. After the second has elapsed, the thread becomes Runnable again and, if the processor becomes available, the thread begins running again.

> For each entrance into the Not Runnable state, there is a specific and distinct escape route that returns the thread to the Runnable state. An escape route works only for its corresponding entrance. For example, if a thread has been put to sleep, then the specified number of milliseconds must elapse before the thread becomes Runnable again. The following list describes the escape route for every entrance into the Not Runnable state:

> - If a thread has been put to sleep, then the specified number of milliseconds must elapse.
> - If a thread is waiting for a condition, then another object must notify the waiting thread of a change in condition by calling `notify` or `notifyAll`. More information is available in Synchronizing Threads.
> - If a thread is blocked on I/O, then the I/O must complete.

### Stopping a Thread

> A program doesn't stop a thread like it stops an applet (by calling a method). Rather, a thread arranges for its own death by having a `run` method that terminates naturally. For example, the `while` loop in this `run` method is a finite loop-- it will iterate 100 times and then exit:

> >     public void run() {
> >         int i = 0;
> >         while (i < 100) {
> >             i++;
> >             System.out.println("i = " + i);
> >         }
> >     }

> A thread with this `run` method dies naturally when the loop completes and the `run` method exits.

> Let's look at how the `Clock` applet thread arranges for its own death. You might want to use this technique with your applets. Recall `Clock`'s `run` method:

> >     public void run() {
> >         Thread myThread = Thread.currentThread();
> >         while (clockThread == myThread) {
> >             repaint();
> >             try {
> >                 Thread.sleep(1000);
> >             } catch (InterruptedException e){
> >                 // the VM doesn't want us to sleep anymore,
> >                 // so get back to work
> >             }
> >         }
> >     }

> The exit condition for this `run` method is the exit condition for the `while` loop because there is no code after the `while` loop:

> >     while (clockThread == myThread) {

> This condition indicates that the loop will exit when the currently exiting thread is not equal to `clockThread`. When would this ever be the case?

> When you leave the page, the application in which the applet is running calls the applet's `stop` method. This method then sets the `clockThread` to `null`, thereby telling the main loop in the `run` method to terminate:

> >     public void stop() {    // applets' stop method
> >         clockThread = null;
> >     }

> If you revisit the page, the `start` method is called again and the clock starts up again with a new thread. Even if you stop and start the applet faster than one iteration of the loop, `clockThread` will be a different thread than `myThread` and the loop will still terminate.

### The isAlive Method

> A final word about thread state: The API for the `Thread` class includes a method called `isAlive`. The `isAlive` method returns true if the thread has been started and not stopped. If the `isAlive` method returns false, you know that the thread either is a New Thread or is Dead. If the `isAlive` method returns true, you know that the thread is either Runnable or Not Runnable. You cannot differentiate between a New Thread or a Dead thread. Nor can you differentiate between a Runnable thread and a Not Runnable thread.

| Start of Tutorial > Start of Trail > Start of Lesson | Search