站内搜索: 请输入搜索关键词
当前页面: 在线文档首页 > Java Tutorial 5.0 英文版

Threads in Applets: Examples - Java Tutorial 5.0 英文版

The JavaTM Tutorial
Previous Page Lesson Contents Next Page Start of Tutorial > Start of Trail > Start of Lesson Search
Feedback Form

Trail: Deployment
Lesson: 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 (in the Deployment trail). The second applet this page discusses, SoundExample, shows how to use threads for one-time initialization tasks. SoundExample is featured in Playing Sounds (in the Deployment trail).

This page does not explain basic thread code. To learn about the Java implementation of threads, refer to Threads: Doing Two or More Tasks at Once (in the Deployment trail).

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 (in the Deployment trail) 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 (in a .java source file).)

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 (in the Deployment trail).

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. The Producer/Consumer Example (in the Deployment trail) 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 (in a .java source file), a Thread subclass.
  • The consumer: SoundExample (in a .java source file), 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 (in a .java source file), 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 (in the Deployment trail).

Previous Page Lesson Contents Next Page Start of Tutorial > Start of Trail > Start of Lesson Search
Feedback Form

Copyright 1995-2005 Sun Microsystems, Inc. All rights reserved.