// // Very simple program demonstrating the use of threads. // // Command-line argument is P (number of threads). // // Synchronization via class (static) method. // // ---- Class containing main program -------------------------------- public class ThreadsHello2 { public static void main(String[] args) { if (args.length < 1) { System.err.println("Usage: java ThreadsHello2 numThreads"); System.exit(1); } int P = Integer.parseInt(args[0]); Thread [] threads = new Thread[P]; // Create threads. for (int i = 0; i < P; ++i) threads[i] = new Thread(new Hello2(i)); // Start them up. for (int i = 0; i < P; ++i) threads[i].start(); // Wait for them to finish. // ("join" is declared as possibly throwing an exception, // so to keep the compiler happy we must deal with it.) try { for (int i = 0; i < P; ++i) threads[i].join(); } catch (InterruptedException e) { // should never happen } System.out.println("That's all, folks!"); } } // ---- Class to contain data and code for each thread --------------- class Hello2 implements Runnable { private int myID; // Constructor. public Hello2(int myID) { this.myID = myID; } // Defines behavior of thread using this object -- // invoked by "start()" on thread. public void run() { printMsg(myID); } // Prints "hello" message. // "synchronized" keyword for class method means only one // thread at a time can execute this method. private static synchronized void printMsg(int ID) { System.out.print("hello, world, "); // pointless pause, included to make the effects of // synchronization (or lack thereof) more obvious pause(1); System.out.println("from thread " + ID); } // Sleeps for n milliseconds. private static void pause(int n) { try { Thread.sleep(n); } catch (InterruptedException e) { // should never happen } } }