Overview of Applets |
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 on the page 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 awhile
(ordo...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 thestop
method so that it stops the applet's thread. When the user returns to the applet's page, thestart
method is called again, and the applet can again create a thread to perform the repetitive task.Below is
AnimatorApplet
's implementation of thestart
andstop
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
innew Thread(this)
indicates that the applet provides the body of the thread. It does so by implementing thejava.lang
Runnable
interface, which requires the applet to provide arun
method that forms the body of the thread. We'll discussAnimatorApplet
'srun
method more a little later.Notice that nowhere in the
AnimatorApplet
class is theThread stop
method called. This is because calling theThread 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'srun
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 typeThread
.In
AnimatorApplet
, this instance variable is calledanimatorThread
. Thestart
method sets it to refer to the newly createdThread
object. When the applet needs to kill the thread, it setsanimatorThread
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 checksanimatorThread
, continuing or exiting depending on the value ofanimatorThread
. 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. IfanimatorThread
refers to another thread, then a race condition has occurred:start
has been called so soon afterstop
(or this thread has taken such a long time in its loop) thatstart
has created another thread before this thread reached the top of itswhile
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:
For more information on
- The producer:
SoundLoader
, aThread
subclass.- The consumer:
SoundExample
, anApplet
subclass. Unlike the Synchronizing Threads consumer example,SoundExample
is not aThread
; it doesn't even implement theRunnable
interface. However, theSoundExample
instance methods are executed by at least two threads, depending on the application that executes theSoundExample
applet.- The storage object:
SoundList
, aHashtable
subclass. UnlikeCubbyHole
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.SoundExample
, go to Playing Sounds.
Overview of Applets |