Threads of Control |
The Clock applet shown below displays the current time and updates its display every second. You can scroll this page and perform other tasks while the clock continues to update because the code that updates the clock's display runs within its own thread.
This section highlights and explains the source code for the clock applet in detail. In particular, this page describes the code segments that implement the clock's threaded behavior; it does not describe the code segments that are related to the life cycle of the applet. If you have not written your own applets before or are not familiar with the life cycle of any applet, you may want to take this time to familiarize yourself with the material in The Life Cycle of an Appletbefore proceeding with this page.
Deciding to Use the Runnable Interface
The Clock applet uses the Runnable interface to provide therun()
method for its thread. To run within a Java-compatible browser, the Clock class has to derive from the Applet class. However, the Clock applet also needs to use a thread so that it can continuously update its display without taking over the process in which it is running. (Some, but not all, browsers create a new thread for every applet to prevent a misbehaved applet from taking over the main browser thread. However, you should not count on this when writing your applets; your applets should create their own threads when doing compute-intensive work.) But since the Java language does not support multiple inheritance, the Clock class can not inherit from Thread as well as from Applet. Thus, the Clock class must use the Runnable interface to provide its threaded behavior.Applets are not threads, nor do any existing Java-compatible browsers or applet viewers automatically create threads in which to run applets. Therefore, if an applet needs any threads it must create its own. The Clock applet needs one thread in which to perform its display updates because it updates its display frequently and the user needs to be able to perform other tasks at the same time the clock is running (such as going to another page, or scrolling this one).
The Runnable Interface
The Clock applet provides arun()
method for its thread via the Runnable interface. The class definition for the Clock class indicates that the Clock is a subclass of Applet and implements the Runnable interface. If you are not familiar with interfaces review the information in the Objects, Classes, and Interfaceslesson.The Runnable interface defines a single method calledclass Clock extends Applet implements Runnable {run()
that doesn't accept any arguments and doesn't return a value. Because the Clock class implements the Runnable interface, it must provide an implementation for therun()
method as defined in the interface. However, before explaining the Clock'srun()
method, let's to look at some of the other elements of the Clock code.Creating the Thread
The application in which an applet is running calls the applet'sstart()
method when the user visits the applet's page. The Clock applet creates a Thread,clockThread
, in itsstart()
method and starts the thread.First, thepublic void start() { if (clockThread == null) { clockThread = new Thread(this, "Clock"); clockThread.start(); } }start()
method checks to see ifclockThread
is null. IfclockThread
is null, then the applet has just been loaded or has been previously stopped and a new thread must be created. Otherwise, the applet is already running. The applet creates a new thread with this invocation:Notice thatclockThread = new Thread(this, "Clock");this
--the Clock applet--is the first argument to the thread constructor. The first argument to this Thread constructor must implement the Runnable interface and becomes the thread's target. When constructed in this way, the clock thread gets itsrun()
method from its target Runnable object--in this case, the Clock applet.The second argument is just a name for the thread.
Stopping the Thread
When you leave the page that displays the Clock applet, the application in which the applet is running calls the applet'sstop()
method. The Clock'sstop()
method sets theclockThread
to null. This tells the main loop in therun()
method to terminate (see the next section), eventually resulting in the thread stopping and being garbage collected. the continual updating of the clock.You could usepublic void stop() { clockThread = null; }clockThread.stop()
instead, which would immediately stop the clock thread. However, the Thread class'sstop()
method has a sudden effect, which means that therun()
method might be in the middle of some critical operation when the thread is stopped. For more complexrun()
methods, using Thread'sstop()
method might leave the program in an inconsistent or awkward state. For this reason, it's best to avoid using the Thread class'sstop()
method when possible.If you revisit the page, the
start()
method is called again, and the clock starts up again with a new thread.The Run Method
And finally the Clock'srun()
method implements the heart of the Clock applet and looks like this:As you saw in the previous section, when the applet is asked to stop, the applet sets thepublic void run() { // loop terminates when clockThread is set to null in stop() while (Thread.currentThread() == clockThread) { repaint(); try { clockThread.sleep(1000); } catch (InterruptedException e){ } } }clockThread
to null; this lets therun()
method know when to stop. Thus the first line of therun()
method loops untilclockThread
is null. Within the loop, the applet repaints itself and then tells the Thread to sleep for 1 second (1000 milliseconds). An applet'srepaint()
method ultimately calls the applet'spaint()
method, which does the actual update of the applet's display area. The Clock applet'spaint()
method gets the current time and draws it to the screen.public void paint(Graphics g) { Date now = new Date(); g.drawString(now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds(), 5, 10); }
Threads of Control |