Applets are embeddable Java applications that are expected to be able to start and stop themselves on command. Applets may be asked to start and stop themselves any number of times. A Java-enabled web browser normally starts an applet when the applet is displayed and stops it when the user moves to another page or (in theory) when the user scrolls the applet out of view. To conform to the semantics of the API, we would like an applet to cease its nonessential activity when it is stopped and resume it when started again. (If you’re not familiar with applets, you may want to take a look at Chapter 20, at this point.)
In this section, we will build UpdateApplet
, a
simple base class for an applet that maintains a thread to
automatically update its display at regular intervals. Although
we’re building an applet here, the general technique is
important for all threaded applications.
UpdateApplet
handles the basic starting and
stopping behavior for us:
//file: UpdateApplet.java public class UpdateApplet extends java.applet.Applet implements Runnable { private Thread updateThread; int updateInterval = 1000; public void run( ) { while ( updateThread != null ) { try { Thread.sleep( updateInterval ); } catch (InterruptedException e ) { return; } repaint( ); } } public void start( ) { if ( updateThread == null ) { updateThread = new Thread(this); updateThread.start( ); } } public void stop( ) { if ( updateThread != null ) { Thread runner = updateThread; updateThread = null; // flag to quit runner.interrupt( ); // wake up if asleep } } }
UpdateApplet
is a Runnable
object that alternately sleeps and calls its repaint( )
method. (There’s nothing to paint, though, so
running this applet is kind of boring. Later in this section,
we’ll subclass it to implement a digital clock.) It has two
other public methods: start()
and stop( )
. These are methods of the Applet
class
we are overriding; don’t confuse them with the similarly named
methods of the Thread
class. These
start()
and stop( )
methods are
called by the Java runtime system, to tell the applet when it should
and should not be running.
UpdateApplet
illustrates an environmentally
friendly way to deal with threads in a simple applet.
UpdateApplet
effectively kills its thread each
time the applet is stopped and recreates it if the applet is
restarted. When UpdateApplet
’s
start( )
method is called, we first check to make
sure there is no currently executing updateThread
.
We then create one to begin our execution. When our applet is
subsequently asked to stop, we set a flag indicating that it should
stop and then make sure it is awake by invoking its
interrupt()
method. In our stop( )
method, we set updateThread
to
null
, which serves three purposes: it allows the
garbage collector to clean up the dead Thread
object; it indicates to UpdateApplet
’s
start( )
method that the thread is gone, so that
another one can be started when necessary; and we use it as the flag
to indicate to the running thread that it is time to quit. If you
feel that we have overburdened this variable, you might consider
using a separate boolean variable for the flag condition.
One thing about Applet
s: in truth, an
Applet
’s start()
and
stop( )
methods are guaranteed to be called in
sequence. As a result, we shouldn’t have to check for the
existence of updateThread
in start( )
. (It should always be null.) However, it’s good
programming practice to perform the test. If we didn’t, and for
some reason stop( )
were to fail at its job, we
might inadvertently start a lot of threads.
With
UpdateApplet
doing all of the work for us, we can
now create the world’s simplest clock applet with just a few
lines of code. Figure 8.3 shows our
Clock
. (This might be a good one to run on your
Java wristwatch.)
//file: Clock.java public class Clock extends UpdateApplet { public void paint( java.awt.Graphics g ) { g.drawString( new java.util.Date().toString( ), 10, 25 ); } }
The java.util.Date().toString( )
method creates a
string that contains the current time.
Our Clock
applet provides a good example of a
simple thread; we don’t mind throwing it away and subsequently
rebuilding it if the user should happen to wander on and off of our
web page a few times. But what if the task that our thread handles
isn’t so simple? What if, for instance, we have to open a
socket and establish a connection with another system? One solution
is to use Thread
’s suspend( )
and resume( )
methods, as we’ll
show you in a moment.
Now if you’re concerned about
being so cavalier in creating and discarding
Thread
objects, you might rightly ask if we
couldn’t simply do a little more logic and save our thread.
Perhaps we could teach the start( )
method to have
the existing thread begin again., rather than having to create a new
thread. It should be apparent how to go about this using the
wait()
and notify( )
methods
after you read the next section on thread synchronization.
However, an issue with applets is that we have no control over how a
user navigates web pages. For example, say a user scrolls our applet
out of view, and we pause our thread. Now we have no way of ensuring
that the user will bring the applet back into view before moving on
to another page. And actually, the same situation would occur if the
user simply moves on to another page and never comes back.
That’s not a problem in this simple example, but there may be
cases in which we need to do some application cleanup before we die.
For this situation the Applet API gives us the destroy( )
method.
destroy( )
is called
by the Java runtime system when the applet is going to be removed
(often from a cache). It provides a place at which we can free up any
resources the applet is holding.
Get Learning Java now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.