Please send questions to
st10@humboldt.edu .
/**
* ThreadDemo4
*
* a fourth demo for Threads;
* this one modifies the old Spring 2000 CIS 235 ThreadDemo3.java,
* making it avoid deprecated Thread methods.
* It uses an AWT Applet and the Runnable interface, also,
* but adds "stop" AND "resume" buttons for *each* of the threads;
*
* RECOMMENDED SIZE: height 200, width 300
*
* modified by: Sharon M. Tuttle
* last modified: 3-12-01
**/
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
public class ThreadDemo4 extends Applet implements Runnable, ActionListener
{
// threads to be started up within this applet
Thread myThread1, myThread2, myThread3;
Button suspT1, suspT2, suspT3, resT1, resT2, resT3;
// let us know whether thread is currently "suspended"
boolean thread1Suspended, thread2Suspended, thread3Suspended;
// can I set ThreadLocal object numIterations here?
static ThreadLocal numIterations = new ThreadLocal();
public void init()
{
setBackground(Color.lightGray);
Label describe = new Label("ThreadDemo4: Version 1.0");
add(describe);
Label filler = new Label("Spring 2001");
add(filler);
suspT1 = new Button("Suspend Thread 1");
add(suspT1);
suspT1.addActionListener(this);
resT1 = new Button("Resume Thread 1");
add(resT1);
resT1.addActionListener(this);
suspT2 = new Button("Suspend Thread 2");
add(suspT2);
suspT2.addActionListener(this);
resT2 = new Button("Resume Thread 2");
add(resT2);
resT2.addActionListener(this);
suspT3 = new Button("Suspend Thread 3");
add(suspT3);
suspT3.addActionListener(this);
resT3 = new Button("Resume Thread 3");
add(resT3);
resT3.addActionListener(this);
}
// creates and starts up my threads --- is executed every time the
// user comes into the applet context after moving away?
public void start()
{
// for each of the 3 threads not yet started,
// start them up
if (myThread1 == null)
{
// ...start it up for this applet,
// naming this thread "My Thread #1"
myThread1 = new Thread(this, "My Thread #1");
thread1Suspended = false;
myThread1.start();
}
if (myThread2 == null)
{
myThread2 = new Thread(this, "My Thread #2");
thread2Suspended = false;
myThread2.start();
}
if (myThread3 == null)
{
myThread3 = new Thread(this, "My Thread #3");
thread1Suspended = false;
myThread3.start();
}
}
// run() is called by the system after thread has been started
// by the system
public void run()
{
Thread executingThread;
String threadName = "";
Integer numIts;
// this will help me to determine the currently-
// executing thread, for display purposes;
executingThread = Thread.currentThread();
while ((myThread1 == executingThread)||
(myThread2 == executingThread)||
(myThread3 == executingThread))
{
System.out.println("This thread is: " +
executingThread.getName());
// how many times has this loop iterated
// for this thread?
numIts = (Integer) numIterations.get();
if (numIts == null)
{
numIts = new Integer(1);
}
else
{
numIts = new Integer(numIts.intValue() + 1);
}
numIterations.set(numIts);
System.out.println(" its loop iteration: " +
numIts);
try
{
// one second pause
Thread.sleep(1000);
// is this where synchronized clause can go?
// (wait needs to be able to have an InterruptedException
// caught, so we'll put it in sleep's try-catch, too.)
synchronized(this)
{
while (((myThread1 == executingThread)&&
(thread1Suspended))
|| ((myThread2 == executingThread) &&
(thread2Suspended))
|| ((myThread3 == executingThread) &&
(thread3Suspended)))
{
wait();
}
}
}
catch(InterruptedException e)
{
// no action, but catch is required
}
}
}
// suspends execution when the user leaves the page
public void stop()
{
if (myThread1 != null)
{
// this is the preferred way to "stop" a
// thread... set it to null?
// (note that this *will* stop its
// while loop in run()!)
myThread1 = null;
}
if (myThread2 != null)
{
// release system resources for that thread
myThread2 = null;
}
if (myThread3 != null)
{
// release system resources for that thread
myThread3 = null;
}
}
// do I need to add synchronized keyword to the method declaration?
public synchronized void actionPerformed(ActionEvent e)
{
String actionCmd;
actionCmd = e.getActionCommand();
// handle specified button suspension or resumption
if (actionCmd.equals("Suspend Thread 1"))
{
thread1Suspended = true;
}
else if (actionCmd.equals("Suspend Thread 2"))
{
thread2Suspended = true;
}
else if (actionCmd.equals("Suspend Thread 3"))
{
thread3Suspended = true;
}
else if (actionCmd.equals("Resume Thread 1"))
{
thread1Suspended = false;
notify(); // let waiters know!
}
else if (actionCmd.equals("Resume Thread 2"))
{
thread2Suspended = false;
notify(); // let waiters know!
}
else if (actionCmd.equals("Resume Thread 3"))
{
thread3Suspended = false;
notify(); // let waiters know!
}
}
}