Java Tip 8: Threads, Netscape, and the resize problem

How to deal with applet resizing in Netscape Navigator

This week's tip comes from Noah Green. Noah discusses his solution to the weird behavior of applets when they are resized.

When you resize the browser window in Netscape, it will always do the following to any applet running on the page:

1. Call its stop() method

2. Call both of its resize() methods (resize(int,int) and

resize (dimension) )

3. Call its start() method

If your program uses threads, you should be careful how you write your start and stop methods. In most sample applet code, the stop() method calls stop on any separate threads within the applet, and then sets them to null. This is because most people think of the stop() method as something called when the user leaves the page and wants to forget about it. But since Netscape calls stop() when you resize the window, your users would lose the applet's state when they thought they were only making a minor adjustment.

The solution is to always suspend threads, not stop them, in the stop method. In the start() method, you resume them. For example:

public void stop() {
    if (extraThread != null && extraThread.isAlive() )
public void start() {
    if (extraThread == null)
    extraThread = new Thread();

We still have a problem: how to dispose of threads once the user really is done. We don't want all these suspended threads hanging around now, do we?

First, we need to distinguish when stop() is being called by leaving the page, and when it's being called by resizing. The problem is that there is no way to do this. Recall that when Netscape does resizing, it calls stop() before it calls any resize() methods, not after, so the state is the same.

There are probably better solutions to this problem than my hack. But here it is anyway: create a new thread called killThread, a subclass of Thread whose run() body kills off all extra threads by calling the applet's destroy() method. The thread will wait 5 seconds (more or less) before it does this. Here's such a thread:

class KillThread extends Thread {
    Applet parent;
    final int KILLTHREADINTERVAL = 5000;      // 5 seconds
    public KillThread (Applet p) {
    parent = p;
    public void run () {
    try {
    } catch (InterruptedException e) {} 

Meanwhile, make sure your applet's destroy() method is written to kill off extraThread, and this killThread:

    public void destroy() {
    if (extraThread != null) {
        extraThread = null;
    if (killThread != null) {
        killThread = null;

How do we use this killThread? We instantiate and run it at the beginning of the applet's stop() method. We stop and kill it at the beginning of the applet's start() method. In this way, we solve the problem of figuring out whether we were resizing or not. The sequence of events is:

1. Netscape calls the stop() method, and a killThread starts.

2. If 5 seconds elapse without the start() method being called, then the user has probably left the page. killThread calls destroy(), which terminates all the applet's extant threads.

If start() is called again, then it means that this was only a resize. Stop and nullify the killThread before it wrecks everything. Resume all the suspended threads, and continue running.

Here are the final versions of the applet's start() and stop() methods:

    public void start() {
    // If we were in the middle of kill thread  
(caused by resizing)
    // stop the killthread and start (i.e. resume)  
    // Otherwise just start as normal
    if (killThread != null) {   
        System.out.println ("KILLTHREAD STOPPED");
        killThread = null;
    // Now start running the extraThread thread
    if ( extraThread == null ) {
        extraThread = new Thread(this);
    public void stop () {
    // First suspend the extraThread thread
    if ( (extraThread != null) &&  
(extraThread.isAlive()) ) {
    // Fire up a killthread, which will kill the  
extraThread thread
    // in 5 seconds unless start is called
    if (killThread != null)
        System.out.println ("ERROR - killThread  
shouldn't exist");
    else {
        killThread = new KillThread(this);

(NOTE: This assumes that we keep track of killThread and extraThread as object variables somewhere, which we would most likely be doing anyway.)

There you have it! With this stuff installed, you will never mess up an applet by resizing a Netscape browser again.

You might want to experiment with other browsers, although if they don't do things the way Netscape does, chances are this code will not affect things adversely. Also, the 5-second time limit may need to be shortened or lengthened, depending on the speed of different systems. So far, 5 seconds seem to do it okay on all the systems we've worked with.

I've seen a lot of applets out there that will "break" if you resize your browser window; this fix should put an end to that problem. If anyone knows of a more elegant solution besides launching a killThread, I'd love to hear about it! Happy coding.

John D. Mitchell is yet another UC-Berkeley Computer Science graduate weaned on caffeine, sugar, and way too little sleep. He spent three years toiling on PDA software at Geoworks for stock that is actually worth more than wallpaper. After the first public release of Java, John bailed out of his day job to develop applets and a Java compiler. He funds his Java addiction by writing compilers, TCL/TK, Perl, C++, and Java systems. His copious spare time is consumed by moderating the comp.lang.tcl.announce newsgroup and writing an awesome Java book.