The Java TM Tutorial

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

Trail: Writing Applets
Lesson: Practical Considerations when Writing Applets

## Threads in Applets: Examples

> This page discusses two examples of using threads in applets. The first applet, AnimatorApplet, shows how to use a thread to perform repeated tasks. AnimatorApplet is from the page Creating the Animation Loop. The second applet this page discusses, SoundExample, shows how to use threads for one-time initialization tasks. SoundExample is featured in Playing Sounds.

> This page does not explain basic thread code. To learn about the Java implementation of threads, refer to Threads of Control.

### Using a Thread to Perform Repeated Tasks

> An applet that performs the same task over and over again typically should have a thread with a `while` (or `do...while`) loop that performs the task. A typical example is an applet that performs timed animation, such as a movie player or a game. Animation applets need a thread that requests repaints at regular intervals. Another example is an applet that reads data supplied by a server-side application. (See Using a Server to Work Around Security Restrictions for such an example.)

> Applets typically create threads for repetitive tasks in the applet `start` method. Creating the thread there makes it easy for the applet to stop the thread when the user leaves the page. All you need to do is implement the `stop` method so that it stops the applet's thread. When the user returns to the applet's page, the `start` method is called again, and the applet can again create a thread to perform the repetitive task.

> Below is `AnimatorApplet`'s implementation of the `start` and `stop` methods. (Here is all of the applet's source code.)

> >     public void start() {
> >         if (frozen) {
> >             //Do nothing.  The user has requested that we
> >             //stop changing the image.
> >         } else {
> >             //Start animating!
> >             if (animatorThread == null) {
> >                 animatorThread = new Thread(this);
> >             }
> >             animatorThread.start();
> >         }
> >     }

> >     public void stop() {
> >         animatorThread = null;
> >     }

> The `this` in `new Thread(this)` indicates that the applet provides the body of the thread. It does so by implementing the `java.lang` `Runnable` interface, which requires the applet to provide a `run` method that forms the body of the thread. We'll discuss `AnimatorApplet`'s `run` method more a little later.

> Notice that nowhere in the `AnimatorApplet` class is the `Thread stop` method called. This is because calling the `Thread stop` method is like clubbing the thread over the head. It's a drastic way to get the thread to stop what it's doing. Instead, you can write the thread's `run` method in such a way that the thread will gracefully exit when you tap it on the shoulder. This shoulder tap comes in the form of setting to null an instance variable of type `Thread`.

> In `AnimatorApplet`, this instance variable is called `animatorThread`. The `start` method sets it to refer to the newly created `Thread` object. When the applet needs to kill the thread, it sets `animatorThread` to null. This kills the thread not by making it be garbage collected -- it can't be garbage collected while it's runnable -- but because at the top of its loop, the thread checks `animatorThread`, continuing or exiting depending on the value of `animatorThread`. Here's the relevant code:

> >     public void run() {
> >         . . .
> >         while (Thread.currentThread() == animatorThread) {
> >             ...//Display a frame of animation and then sleep.
> >         }
> >     }

> If `animatorThread` refers to the same thread as the currently executing thread, the thread continues executing. If, on the other hand, `animatorThread` is null, the thread exits. If `animatorThread` refers to another thread, then a race condition has occurred: `start` has been called so soon after `stop` (or this thread has taken such a long time in its loop) that `start` has created another thread before this thread reached the top of its `while` loop. Whatever the cause of the race condition, this thread should exit.

> For more information about `AnimatorApplet`, go to Creating the Animation Loop.

### Using a Thread to Perform One-Time Initialization

> If your applet needs to perform some initialization task that can take a while, you should consider ways of performing the initialization in a thread. For example, anything that requires making a network connection should generally be done in a background thread. Fortunately, GIF and JPEG image loading is automatically done in the background using threads that you don't need to worry about.

> Sound loading, unfortunately, is not guaranteed to be done in the background. In current implementations, the `Applet getAudioClip` methods don't return until they've loaded all the audio data. As a result, if you want to preload sounds, you might want to create one or more threads to do so.

> Using a thread to perform a one-time initialization task for an applet is a variation of the classic producer/consumer scenario. The thread that performs the task is the producer, and the applet is the consumer. Synchronizing Threads discusses how to use Java threads in a producer/consumer scenario.

> SoundExample adheres closely to the model presented in Synchronizing Threads. Like the Synchronizing Threads example, SoundExample features three classes:

> - The producer: `SoundLoader`, a `Thread` subclass.
> - The consumer: `SoundExample`, an `Applet` subclass. Unlike the Synchronizing Threads consumer example, `SoundExample` is not a `Thread`; it doesn't even implement the `Runnable` interface. However, the `SoundExample` instance methods are executed by at least two threads, depending on the application that executes the `SoundExample` applet.
> - The storage object: `SoundList`, a `Hashtable` subclass. Unlike `CubbyHole` in the Synchronizing Threads example, `SoundList` can return null values if the sound data hasn't been stored yet. This makes sense for this applet because it needs to be able to react immediately to a user request to play the sound, even if the sound hasn't been loaded yet.
> For more information on `SoundExample`, go to Playing Sounds.

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