import java.util.*; import static java.lang.System.out; /** The Project 3 main class. *
* CS 537, Spring 2007, Project 3. */ public class P3 { /** Source version number. */ private static final int VERSION = 2; /** Number of Brewers. */ private static int brewerCount; /** The unique Warehouse. */ private static Warehouse warehouse; /** Brewers. */ private static Brewer[] brewers; /** Brewer threads. */ private static Thread[] brewerThreads; /** The unique supplier. */ private static Supplier supplier; /** Startup time (used to support the time() method. */ static private long startTime = System.currentTimeMillis(); /** Flag to control debugging output. */ private static boolean verbose = false; /** Turns debugging output on or off. * @param on if true, turn debugging on; otherwise turn it off. */ public static void setVerbose(boolean on) { verbose = on; } // setVerbose(boolean) /** Returns the unique Warehouse instance. * * @return the warehouse. */ public static Warehouse getWarehouse() { return warehouse; } // getWarehouse() /** If the debugging flag is on, prints a message, preceded by the * name of the current thread. If it is off, does nothing. * @param message the message to print. */ public static void debug(Object message) { if (verbose) { out.printf("%6.3f %s: %s%n", time() / 1E3, Thread.currentThread().getName(), message); } } // debug(Object) /** If the debugging flag is on, prints a message, preceded by the * name of the current thread. If it is off, does nothing. * @param format a printf-like format for the message * @param args arguments to the printf */ public static void debug(String format, Object... args) { if (verbose) { String message = String.format(format, args); out.printf("%6.3f %s: %s%n", time() / 1E3, Thread.currentThread().getName(), message); } } // debug(String,Object...) /** Handy procedure for timing. * @return the elapsed time since startup, in milliseconds. */ static public int time() { return (int)(System.currentTimeMillis() - startTime); } // time() /** Returns the number of Brewers in the system. * @return the number of Brewers. */ public static int brewers() { return brewerCount; } // brewers() /** Random number generator. */ private static Random rand; /** Utility to generate a random non-negative integer less than max. * @param max integer one greater than the largest possible result. * @return a non-negative integer strictly less than max. */ public static int randInt(int max) { if (0 >= max) { throw new IllegalArgumentException("randInt"); } return (rand.nextInt(max)); } // randInt(int) /** Utility to generate a random integer between min and max (inclusive). * @param min the smallest possible result. * @param max the largest possible result. * @return an integer between min and max, inclusive. */ public static int randInt(int min, int max) { if (min >= max) { throw new IllegalArgumentException("randInt"); } return min + rand.nextInt(max - min + 1); } // randInt(int,int) /** Generates an exponentially distributed random number. * @param mean the mean of the distribution. * @return the next sample value. */ public static int expo(int mean) { return (int) Math.round(-Math.log(rand.nextDouble()) * mean); } // expo(int) /** Prints a usage message and terminates. */ private static void usage() { System.err.println( "usage: P3 [-v][-r] algorithm brewerCount iterations"); System.exit(1); } // usage() /** Main program for project 3. * @param args the command-line arguments. */ public static void main(String[] args) { // Parse command-line arguments GetOpt options = new GetOpt("P3", args, "vr"); int opt; while ((opt = options.nextOpt()) != -1) { switch (opt) { default: usage(); break; case 'v': verbose = true; break; case 'r': rand = new Random(0); break; } } if (rand == null) { rand = new Random(); } if (options.optind != args.length - 3) { usage(); } int algorithm = Integer.parseInt(args[options.optind + 0]); brewerCount = Integer.parseInt(args[options.optind + 1]); int iterations = Integer.parseInt(args[options.optind + 2]); // Create the warehouse. warehouse = new Warehouse(algorithm); Thread wthread = new Thread(warehouse, "Warehouse"); // Create the Supplier supplier = new Supplier(iterations); Thread supplierThread = new Thread(supplier, "Supplier"); // Create the Brewers brewers = new Brewer[brewerCount]; brewerThreads = new Thread[brewerCount]; for (int i = 0; i < brewerCount; i++) { brewers[i] = new Brewer(i); brewerThreads[i] = new Thread(brewers[i], "Brewer" + i); } // Start the threads running // They all have lower priority than the main thread so none of them // will run until we are done starting them all. wthread.setPriority(Thread.NORM_PRIORITY - 1); wthread.start(); supplierThread.setPriority(Thread.NORM_PRIORITY - 1); supplierThread.start(); for (Thread t : brewerThreads) { t.setPriority(Thread.NORM_PRIORITY - 1); t.start(); } // Wait for all the threads to finish try { // The supplier thread returns when it has completed the requested // number of iterations. supplierThread.join(); // Wait three seconds to give everyone a chance to finish // whatever they're doing, then kill them all off. Thread.sleep(3000); // Kill off the warehouse thread wthread.interrupt(); wthread.join(); // Kill off the brewers for (Thread t : brewerThreads) { t.interrupt(); t.join(); } } catch (InterruptedException e) { e.printStackTrace(); } // Display final state. out.printf("**** Program terminating%n"); Order amt; Order balance = new Order(); int produced = 0; int inWarehouse = 0; int consumed = 0; amt = supplier.getProduction(); out.printf("Produced %s%n", amt); balance.change(amt); produced += amt.total(); amt = warehouse.getAmountOnHand(); for (Grain c1 : Grain.values()) { int n = amt.get(c1); balance.change(c1, -n); inWarehouse += n; } Order totalConsumed = new Order(); int totalRequests = 0; int totalWaiting = 0; for (int i = 0; i < brewerCount; i++) { amt = brewers[i].getConsumption(); int requests = brewers[i].requestsCompleted(); int waiting = brewers[i].waitingTime(); totalConsumed.change(amt); for (Grain g : Grain.values()) { int n = amt.get(g); balance.change(g, -n); consumed += n; } out.printf("Brewer %d%n", i); out.printf(" Grain consumed: %s%n", amt); out.printf(" Completed requests: %d%n", requests); out.printf(" Total waiting time: %d ms%n", waiting); if (requests > 0) { out.printf(" Mean waiting time: %.2f ms%n", waiting / (double)requests); } totalRequests += requests; totalWaiting += waiting; } out.printf("Net excess (deficit) is %s%n", balance); out.printf( "Total: produced = %d, consumed = %d," + " remaining in warehouse = %d, net = %d%n", produced, consumed, inWarehouse, (produced - consumed - inWarehouse)); out.printf( "Requests completed: %d, mean waiting time %.2fms%n", totalRequests, totalWaiting / (double) totalRequests); } // main(String[]) } // P3