Threads1

Main.java  [download]

import java.awt.*;
import javax.swing.*;
import java.util.concurrent.*; //*3 Use special thread-safe implementations

/**
 * Main program for Threads demo
 */
public class Main extends JFrame {
    /** Our Row's */
    private CopyOnWriteArrayList<Row> rows = new CopyOnWriteArrayList<Row> (); //*3

    public static void main (String [] args) {
	java.awt.EventQueue.invokeLater (new Runnable() {
            public void run() {
		new Main ();
            }
        });
    }

    public Main () {
	// Window setup
	setSize (500, 500);
	Container content = getContentPane();
	setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

	// Our canvas
	MyCanvas canvas = new MyCanvas (this);
	content.add (canvas);

	// Show our window
	setVisible (true);

	// Now create our Row's and start() them
	for (int i=0; i<5; i++) { //*1 Create our Row's, start() them, remember them in ivar
	    Row r = new Row (new Rectangle (10, 100+i*75, 500-40, 40), canvas); //*1
	    rows.add (r); //*1
	}
    }

    public void drawCanvas (Graphics g) {
	// Draw each of our Row's
	for (Row r: rows) r.draw (g); //*2 Draw each of our Row's
    }
}

MyCanvas.java  [download]

import java.awt.*;
import javax.swing.*;

/**
 * Canvas, is pretty much a captive of Main
 */
public class MyCanvas extends JPanel {
    private Main parent;

    public MyCanvas (Main parent) {
	this.parent = parent;
    }

    /** Tell parent to do the job */
    public void paintComponent (Graphics g) {
	super.paintComponent(g);
	parent.drawCanvas (g);
    }
}

Row.java  [download]

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

/**
 * A process that grabs Box's and draws a row of them
 */
public class Row implements Runnable { //*1 We use a thread
    private MyCanvas canvas;
    private Rectangle loc;
    private CopyOnWriteArrayList<Box> boxes = new CopyOnWriteArrayList<Box> (); //*4 We maintain list of our Box's

    public Row (Rectangle loc, MyCanvas canvas) {
	this.loc = loc;
	this.canvas = canvas;

	// Start a new thread to run us
	Thread thread = new Thread (this); //*1
	thread.start(); //*1
    }

    /**
     * Method for Runnable
     */
    public void run () { //*2 What thread does when you run() it
	for (int i=0; i<10; i++) { //*2
	    boxes.add (new Box ()); //*2
	    // Since we've just changed our box list, request a repaint
	    canvas.repaint (); //*2

	    try {
		Thread.sleep (2000); // 2 seconds //*2
	    } catch (InterruptedException e) { }
	}
	System.out.println ("Row at y = " + loc.y + " finished"); //*3 Thread is about to die, print message
    }
	
    public void draw (Graphics g) {
	Graphics2D g2 = (Graphics2D) g;

	g2.draw (loc);

	// We tell each Box where to draw itself
	int boxsize = loc.height-2*5;
	Rectangle boxloc = new Rectangle (loc.x+10, loc.y+5,
					  boxsize, boxsize);

	// Draw each of our Box's
	for (Box b: boxes) { //*4
	    b.draw (g, boxloc); //*4
	    boxloc.x = boxloc.x + boxsize + 10; //*4
	}
    }
}

Box.java  [download]

import java.awt.*;
import javax.swing.*;

/**
 * A little box with a number inside it,
 * belongs to a Row
 */
public class Box {
    /** Classvar counter for next ID number */
    static private int nextID = 1;
    
    /** Our own ID number */
    private int id;

    public Box () {
	// Take next available ID number
	id = nextID++;
    }

    public void draw (Graphics g, Rectangle loc) {
	Graphics2D g2 = (Graphics2D) g;

	g2.setColor (Color.BLACK);
	g2.fill (loc);
	g2.setColor (Color.WHITE);
	g2.drawString (String.valueOf (id), loc.x+5, loc.y+15); 
	g2.setColor (Color.BLACK);
   }
}