/* Java application having as its purpose to demonstrate the use of ** threads. ** */ public class Demo1 { public static void main(String[] args) throws InterruptedException { // Expected are two command-line arguments, the first of which is // to indicate which of the two methods below is to be executed // and the second of which is to indicate by how much the Counter(s) // are to be increased. int whichOne = Integer.parseInt(args[0]); int increaseVal = Integer.parseInt(args[1]); if (whichOne == 1) { demo1(increaseVal); } else if (whichOne == 2) { demo2(increaseVal); } else { System.out.println("First arg must be 1 or 2"); } } /* This method creates a CounterIncreaser object, whose two components ** are a Counter object and an int value indicating how many times ** that the Counter is to be incremented. A thread is created for ** the purpose of having the CounterIncreaser object carry out ** its mission, which is to increment the Counter the specified # ** of times. */ public static void demo1(int increaseVal) throws InterruptException { Counter cntr = new Counter(); CounterIncreaser ci = new CounterIncreaser(cntr, increaseVal); Thread t = new Thread(ci); t.start(); t.join(); System.out.println("cntr says " + cntr.countVal()); } /* This method is similar to the one above, except that it creates ** two CounterIncreaser objects and, using two threads, has each ** one increment the same Counter a specified number of times. ** The point is to illustrate not only the use of threads but ** also that when two threads modify the same memory location, ** the results may be unexpected or unintended. */ public static void demo2(int increaseVal) throws InterruptedException { Counter cntr = new Counter(); CounterIncreaser ci1 = new CounterIncreaser(cntr, increaseVal); CounterIncreaser ci2 = new CounterIncreaser(cntr, increaseVal); Thread t1 = new Thread(ci1); Thread t2 = new Thread(ci2); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("cntr says " + cntr.countVal()); } }