Please send questions to
st10@humboldt.edu .
/**
* ThreadDemo1
*
* modified and adapted from "Java Examples in a Nutshell", SECOND
* edition, Flanagan, O'Reilly, pp. 71-72, in Example 4-1,
* ThreadDemo.java
*
* (comments in quotes are directly quoted from Flanagan's
* ThreadDemo.java)
*
* "This class demonstrates the use of threads. The main() method
* is the initial method invoked by the interpreter. It defines and
* starts two more threads and the three threads run at the same time.
* Note that this class extends Thread and overrides its run() method.
* That method provides the body of one of the threads started by the
* main() method."
*
* modified by: Sharon M. Tuttle
* last modified: 3-12-01
**/
public class ThreadDemo1 extends Thread
{
/**
* "This method overrides the run() method of Thread. It
* provides the body of this thread."
* (this is the run() that thread1 below will do)
**/
public void run()
{
for (int i=0; i<5; i++)
{
// see method compute() below, in this file
compute();
}
}
/**
* "This main method creates and starts two threads in addition
* to the initial thread that the interpreter creates to invoke
* the main() method."
**/
public static void main(String args[])
{
ThreadDemo1 thread1; // a thread that is an instance of
// this class that will be created
// here;
Thread thread2; // a thread that will be created
// using the Thread constructor;
// "Create the first thread: an instance of this class.
// Its body is the run() method above."
thread1 = new ThreadDemo1();
thread1.setName("thread1"); // setting its name
// "Create the second thread by passing a Runnable object
// to the Thread constructor. The body of this thread is
// the run() method of the anonymous Runnable object below."
// [the second argument after the anonymous Runnable object
// is setting the name of this thread)
thread2 = new Thread(
new Runnable()
{
public void run()
{
for (int i=0; i<10; i++)
{
compute();
}
}
}, "thread2"
);
// "Set the priorities of these two threads, if any
// are specified."
if ((args != null) && (args.length >= 1))
{
try
{
thread1.setPriority(Integer.parseInt(args[0]));
}
catch (NumberFormatException exc)
{
System.err.println("Ignoring erroneous priority: " +
args[0] + "\n and starting thread1 with" +
" no specified priority");
}
catch (IllegalArgumentException exc)
{
System.err.println("Requested thread1 priority of " +
args[0] + " is more than maximum " +
"permitted\n priority of thread1's " +
"thread group: " + Thread.MAX_PRIORITY);
}
// only if there was 1 arg might there be 2...!
if (args.length >= 2)
{
try
{
thread2.setPriority(Integer.parseInt(args[1]));
}
catch (NumberFormatException exc)
{
System.err.println("Ignoring erroneous priority: " +
args[1] + "\n and starting thread2 with" +
" no specified priority");
}
catch (IllegalArgumentException exc)
{
System.err.println("Requested thread2 priority of " +
args[1] + " is more than maximum " +
"permitted\n priority of thread2's " +
"thread group: " + Thread.MAX_PRIORITY);
}
}
}
// "Start the two threads running"
thread1.start();
thread2.start();
// "This main() method is run by the initial thread
// created by the Java interpreter. Now that thread
// does some stuff, too."
for (int i=0; i<3; i++)
{
compute();
}
// "We could wait for the threads to stop running
// with these lines. But they aren't necessary here,
// so we won't bother."
// try
// {
// thread1.join();
// thread2.join();
// }
// catch (InterruptedException exc)
// {}
// "The Java VM exits only when the main() method returns,
// and when all threads stop running (except for daemon
// threads --- see setDaemon())."
}
// "ThreadLocal objects [added as of Java 1.2!] represent a
// value accessed with get() and set(). But they maintain a
// different value for each thread. This object keeps track of
// how many times each thread has called compute()."
static ThreadLocal numCalls = new ThreadLocal();
/** "This is the dummy method our threads all call."
**/
static synchronized void compute()
{
Integer n; // number of times compute() has been called
// by current thread
// "Figure out how many times we've been called by the
// current thread."
n = (Integer) numCalls.get();
if (n == null) // numCalls has no object associated with it,
// initially;
{
n = new Integer(1);
}
else
{
n = new Integer(n.intValue() + 1);
}
// now set a new value for this numCalls object;
numCalls.set(n);
// "Display the name of the thread, and the number of
// times [compute() has been] called [by that thread]"
System.out.println(Thread.currentThread().getName() +
": " + n);
// "Do a long computation, simulating a "compute-bound"
// thread"
for (int i=0, j=0; i < 1000000; i++)
{
j += i;
}
// "Alternatively, we can simulate a thread subject to
// network or I/O delays by causing it to sleep for a random
// amount of time:"
try
{
// "Stop running for a random number of milliseconds"
// [note: sleep() NEEDS to be in a try-catch block!]
Thread.sleep((int)(Math.random()*1000 + 1));
}
catch (InterruptedException exc)
{}
// "Each thread politely offers the other threads a chance
// to run. This is important so that a compute-bound thread
// does not "starve" other threads of equal priority."
Thread.yield();
}
}