notes


Threads

Why Threads?

In simple programs that just run the main method of some class, there is just one sequence of commands being executed. Each line in the body of the main program is executed in turn, loops are looped over, conditionals are evaluated and decisions are made, but in the end, there was just one continuous thread of execution. It is possible, however, to have (the appearance of) different sequences of commands running in parallel. A standard one processor machine can of course only process one instruction at a time, but the appearance of parallel threads is maintained, and their presence is a great convenience.

We'll look at very simple thread use in the context of animating applets. If you want to make an animation, you can't just do the animating in the body of the paint method. This method is expected to return quickly. It shouldn't do anything that takes a long time. This is because the paint method runs in the browser's thread. It's sort of borrowing time, and can't borrow much. To do anything that takes time, like an animation, you need to create your own thread.


Making Threads

First, to make a thread, you need to give the thread some code to run. To do this, you need to have some class that has a run method (returning nothing and taking no arguments) and is declared to implement the Runnable interface. The Runnable interface is like this:

interface Runnable
{
  public void run();
}

Except you'll never write the above lines of code into a java file. The Runanble interface is provided with Java. Once you have a class implementing Runnable and providing a run method, you construct a Thread object. This Thread object's constructor takes as a single argument an instance of your class providing the run method. Once the thread is constructed, you can start it by calling it's start method. It'll look something like this:

public class SomeClass implements Runnable
{
  public void run()
  {
    // some code goes here...
  }

  public static void main(String[] args)
  {
    SomeClass sc = new SomeClass();
    Thread t = new Thread(sc);
    t.start();
  }   
}

Threading Applets

The simplest way to to use Threads to make an animated applet is to make the applet itself have a run method and have as a member object a Thread, which gets started in the init method of the applet. The following code (which is this) makes white circles in random locations on a blue background.

Here is the code:

import java.awt.*;
import java.util.*;

public class Bubbles extends java.applet.Applet implements Runnable
{
  Thread t;          // the thread that will do the animation
  int x,y;           // next dot location
  int width,height;  // width and height of the applet

  public void run()
  {
    Random r = new Random();                  // get a Random
    while(true)                               // then loop forever
    {
      x = (int)(r.nextDouble() * width);      // random x
      y = (int)(r.nextDouble() * height);     // random y
      repaint();                              // paint next circle
      try { Thread.sleep(10); }               // sleep a little
      catch (InterruptedException e) { ; }
    }
  }

  public void init()
  {
    setBackground( new Color(0,0,100) );
    width = getSize().width;
    height = getSize().height;
    t = new Thread(this);
    t.start();
  }

  public void update(Graphics g)
  {
    paint(g);
  }

  public void paint(Graphics g)
  {
    g.setColor(Color.white);
    g.drawOval(x-3,y-3,6,6);
  }     
}

What's going on?

When the browser creates a Bubbles applet, it first calls init on it. Here, the background is set, the width and height are determined, and an animating thread is created and started. From there, the browser gets its own processing thread back. It is important that init doesn't take long because the browser is frozen while init is running.

After the browser gets its thread back, the thread created in init is still alive, and has begun executing the Bubbles run method. This method creates a Random object to provide random numbers and then starts on an infinite loop. That loop gets a new random position for the next bubble, calls repaint, and sleeps for ten seconds. Since the sleep method (a static method of the Thread class) can throw an InterruptedException (I have no idea what that would mean) you need to catch it like in the above loop.

Now, you might wonder: what's with the repaint method? Why not just call paint? The reason for that is that you don't actually have constant access to the screen. The screen is only repainted at regular intervals, the exact length of which is determined by the refresh rate of your video system. So what repaint does is tell the Java Virtual Machine that it should call update on the applet the next time its making a screen refresh. Here you have to remember that while one sixtieth of a second might seem tiny, its actually a whole lot of time on the computer. On a 1 GHz machine being sold today, its about 17 million CPU clock cycles.

Our update method above just calls paint, which then draws a white circle at the position determined by the x and y values obtained from the Random object in the animation loop. Note that x and y are variables (members) inside of the Bubbles object. Each iteration of the animation loop in run, they are set to new values. Each refresh of the screen, paint gets the latest values and uses them to draw the next bubble.