Home Page
>
Deployment
>
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.
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
Defining and Starting a Thread.
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.
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 animation applets, see
Creating the Animation Loop, a section in
Creating a GUI with JFC/Swing.
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, PNG, 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.
Synchronization 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.