Runnable Interface

RandomCharacters.java

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

public class RandomCharacters extends JApplet
                              implements Runnable,
                                         ActionListener {
   private String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   private JLabel outputs[];
   private JCheckBox checkboxes[];
   private final static int SIZE = 3;
   
   private Thread threads[];
   private boolean suspended[];

   public void init()
   {
      outputs = new JLabel[ SIZE ];
      checkboxes = new JCheckBox[ SIZE ];
      threads = new Thread[ SIZE ];
      suspended = new boolean[ SIZE ];

      Container c = getContentPane();
      c.setLayout( new GridLayout( SIZE, 2, 5, 5 ) );

      for ( int i = 0; i < SIZE; i++ ) {
         outputs[ i ] = new JLabel();
         outputs[ i ].setBackground( Color.green );
         outputs[ i ].setOpaque( true );
         c.add( outputs[ i ] );

         checkboxes[ i ] = new JCheckBox( "Suspended" );
         checkboxes[ i ].addActionListener( this );
         c.add( checkboxes[ i ] );
      }
   }

   public void start()
   {
      // create threads and start every time start is called
      for ( int i = 0; i < threads.length; i++ ) {
         threads[ i ] =
            new Thread( this, "Thread " + (i + 1) );
         threads[ i ].start();
      }
   }

   public void run()
   {
      Thread currentThread = Thread.currentThread();
      int index = getIndex( currentThread );
      char displayChar;

      while ( threads[ index ] == currentThread ) {
         // sleep from 0 to 1 second
         try {
            Thread.sleep( (int) ( Math.random() * 1000 ) );

		
		// The following statements define a synchronized block of code.
		// When the Thread reaches the synchronized block, the
		// applet object (this) is locked until the end of the block.
		// If the current thread is marked for suspension, it is placed in a
		// wait mode until notify is called.
		
            synchronized( this ) {
               while ( suspended[ index ] &&
                       threads[ index ] == currentThread )
                  wait();
            }
         }
         catch ( InterruptedException e ) {
            System.err.println( "sleep interrupted" );
         }
         
         displayChar = alphabet.charAt(
                          (int) ( Math.random() * 26 ) );
         outputs[ index ].setText( currentThread.getName() +
            ": " + displayChar );
      }

      System.err.println(
         currentThread.getName() + " terminating" );
   }

   private int getIndex( Thread current )
   {
      for ( int i = 0; i < threads.length; i++ )
         if ( current == threads[ i ] )
            return i;

      return -1; 
   }

   public synchronized void stop()
   {
      // stop threads every time stop is called
      // as the user browses another Web page
      for ( int i = 0; i < threads.length; i++ ) 
         threads[ i ] = null;

      notifyAll();
   }

   public synchronized void actionPerformed( ActionEvent e )
   {
      for ( int i = 0; i < checkboxes.length; i++ ) {
         if ( e.getSource() == checkboxes[ i ] ) {
            suspended[ i ] = !suspended[ i ];

            outputs[ i ].setBackground(
               !suspended[ i ] ? Color.green : Color.red );

            if ( !suspended[ i ] )
               notify();

            return;
         }
      }
   }
}


Maintained by John Loomis, last updated 15 July 2000