// File: IO24.java (Module 13) // // Author: Rahul Simha // Created: Nov 30, 1998 // // Using start() and stop() import java.awt.*; import java.awt.event.*; import java.applet.*; public class IO24 extends Applet { Canvas c; public void init () { // Frame properties. this.setBackground (Color.cyan); // Must set layout of the panel. this.setLayout (new BorderLayout()); // Quit button. Panel p = new Panel (); Button quitb = new Button ("QUIT"); quitb.addActionListener ( new ActionListener () { public void actionPerformed (ActionEvent a) { System.exit (0); } } ); p.add (quitb); // Pressing "start" calls race() Button startb = new Button ("START"); startb.addActionListener ( new ActionListener () { public void actionPerformed (ActionEvent a) { race (); } } ); p.add (startb); Button pauseb = new Button ("PAUSE"); pauseb.addActionListener ( new ActionListener () { public void actionPerformed (ActionEvent a) { suspend_race (); } } ); p.add (pauseb); Button continueb = new Button ("CONTINUE"); continueb.addActionListener ( new ActionListener () { public void actionPerformed (ActionEvent a) { continue_race (); } } ); p.add (continueb); this.add (p, BorderLayout.SOUTH); // A canvas to draw the results. c = new Canvas(); c.setBackground (Color.white); this.add (c, BorderLayout.CENTER); // Create a ThreadGroup instance. DogGroup = new ThreadGroup ("All dogs"); this.setVisible (true); } ThreadGroup DogGroup; void race () { Dimension D = c.getSize (); // Finish-line is at the right end of the canvas. int finish_line = D.width; // Create two dog instances with different ID's. Dog d1 = new Dog (1, c); Dog d2 = new Dog (2, c); // Create a Thread instance for each dog. // Note: the class Dog must implement the // Runnable interface. Thread d1_thread = new Thread (DogGroup, d1); Thread d2_thread = new Thread (DogGroup, d2); Dog.start_race(); // Start running the threads. // ("start" is a method in Thread). d1_thread.start(); d2_thread.start(); } public void suspend_race () { DogGroup.suspend (); } public void continue_race () { DogGroup.resume (); } public void stop () { DogGroup.suspend (); } public void start () { DogGroup.resume (); } } class Dog implements Runnable { public int position = 20; // Starting position. int ID; // An ID. Canvas c; // The canvas on which to draw. static boolean race_over; public Dog (int ID, Canvas c) { this.ID = ID; this.c = c; // Draw ID on canvas. Graphics g = c.getGraphics (); g.drawString (""+ID, 5, 20*ID+8); } public void move () { // Move a random amount. int new_position = position + (int) UniformRandom.uniform (20,30); // Draw new position. Graphics g = c.getGraphics (); int size = new_position - position; g.fillRect (position, 20*ID, size, 10); position = new_position; } public void run () { // Compute the finish line distance. int finish_line = c.getSize().width; // While not complete... while (position < finish_line) { try { Thread.sleep ((int)UniformRandom.uniform (300,600)); } catch (InterruptedException e) { System.out.println (e); } // Check whether race is over. if (race_finished (false, ID)) break; // Move if race is still on. move (); } if (position >= finish_line) race_finished (true, ID); } public static synchronized void start_race () { race_over = false; } // The same method is called to check whether the race // is complete or to indicate that it is complete. public static synchronized boolean race_finished (boolean set, int ID) { boolean return_val = race_over; if (!set) return_val = race_over; else { // Race overseer sleeps for a while. try { Thread.sleep ((int)UniformRandom.uniform (1000,2000)); } catch (InterruptedException e) { System.out.println (e); } race_over = true; return_val = true; } return return_val; } }