/* * "hello world" program with synchronization * * threads perform I/O with delays, introducing need to ensure one-at-a-time * access to System.out. * * command-line argument specifies number of threads. */ public class HelloSynch { private static Object lockObj = new Object(); /* print message, pausing in the middle -- totally artificial, just * something to show a need for one-at-a-time access to System.out */ public static void helloWithDelay() { /* "synchronized" here ensures one-at-a-time execution */ /* comment it out to see what happens without it */ synchronized (lockObj) { System.out.print("hello again from thread "); try { Thread.currentThread().sleep(10); } catch (InterruptedException e) { System.err.println("this should not happen"); } System.out.println(Thread.currentThread().getName()); } } /* main method */ public static void main(String[] args) { /* process command-line argument */ if (args.length <= 0) { System.err.println("usage: HelloSynch numThreads"); System.exit(1); } int numThreads = 0; try { numThreads = Integer.parseInt(args[0]); } catch (NumberFormatException e) { System.err.println("usage: HelloSynch numThreads"); System.exit(1); } /* create threads */ Thread[] threads = new Thread[numThreads]; for (int i = 0; i < numThreads; ++i) { threads[i] = new Thread(new Runnable() { public void run() { /* "synchronized" here ensures one-at-a-time execution */ /* comment it out to see what happens without it */ synchronized(lockObj) { System.out.println("hello, world, from thread " + Thread.currentThread().getName()); } helloWithDelay(); } }); } /* start them up */ System.out.println("starting threads"); for (int i = 0; i < numThreads; ++i) { threads[i].start(); } /* wait for them to finish */ for (int i = 0; i < numThreads; ++i) { try { threads[i].join(); } catch (InterruptedException e) { System.err.println("this should not happen"); } } System.out.println("threads all done"); } }