Threads and Simple Animation

Everything so far has redrawn PaintApplet in response to something the user did - a drag, a key press, a button click. True animation needs something different: the applet redrawing itself continuously, on its own schedule, whether or not the user is doing anything. That means running a loop on a background Thread.

Note: This page's code is a preview, not something you can run right on this website - this server runs PHP, not a Java runtime. See Environment Setup for how to actually compile and run it.

The Classic Pattern: Runnable + start()/stop()

The applet implements Runnable, giving it a run() method that becomes the body of the animation loop. A Thread wrapping this is created and started inside the applet's own start() lifecycle method, and stopped inside stop():

Lifecycle methodWhat it does for the animation
start()Creates and starts the background Thread
run()Loops: move the ball, call repaint(), sleep a bit, repeat
stop()Signals the loop to end cleanly, via a flag - never by force-killing the thread

Why Not Thread.stop()?

Old Java code sometimes calls the long-removed Thread.stop() method to kill a thread immediately. It's unsafe by design: it can interrupt the thread at literally any point, potentially leaving shared objects in a half-updated, inconsistent state, and it has been deprecated for that reason since very early Java and removed from modern JDKs entirely. The safe, standard pattern instead is a volatile boolean running flag that the loop checks on every iteration, and that stop() simply sets to false - the thread notices on its own next loop check and exits normally, never mid-operation.

Example: BouncingBallApplet

A small standalone example - not a change to PaintApplet - showing the whole pattern: a ball that moves a few pixels per frame and reverses direction when it hits an edge.

import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;

public class BouncingBallApplet extends Applet implements Runnable {

    private volatile boolean running = false;
    private Thread animationThread;

    private int x = 20, y = 20;
    private int dx = 3, dy = 2;
    private static final int SIZE = 20;

    public void start() {
        running = true;
        animationThread = new Thread(this);
        animationThread.start();
    }

    public void stop() {
        // Ask the loop to end - never force-kill it with the removed Thread.stop()
        running = false;
    }

    public void run() {
        while (running) {
            x += dx;
            y += dy;

            if (x <= 0 || x + SIZE >= getWidth()) dx = -dx;
            if (y <= 0 || y + SIZE >= getHeight()) dy = -dy;

            repaint();

            try {
                Thread.sleep(30);  // ~33 frames per second
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                running = false;
            }
        }
    }

    public void paint(Graphics g) {
        g.setColor(Color.ORANGE);
        g.fillOval(x, y, SIZE, SIZE);
    }
}

Why Thread.sleep() needs a try/catch: sleep() declares a checked exception, InterruptedException, that fires if another thread interrupts this one while it's sleeping. You can't just ignore it - the code above re-sets the interrupt status with Thread.currentThread().interrupt() (good practice so the interruption isn't silently swallowed) and also flips running to false, ending the loop on the next check rather than looping forever with a broken sleep.

Why This, Historically

A production-quality Swing application written today would typically use a javax.swing.Timer instead of a raw background thread for this kind of animation - it fires its callback on the Event Dispatch Thread automatically, sidestepping thread-safety concerns with Swing components entirely. Raw threads are what's traditionally taught alongside applets, though, since Applet predates javax.swing.Timer's common use and the Runnable/Thread pattern above is what you'll actually find in most applet-era code and course material.

Next steps: You now have the full AWT toolkit: graphics, events, images, audio, layout, components, and animation. Head to Why Applets Are Deprecated, and What to Use Instead for an honest look at where this technology stands today.