import java.util.List; /** * Generic example of master/worker program. * "Tasks" just consist of sleeping for a specified time; times to wait are * generatedly randomly from 1 to a specified maximum. * * Command-line arguments: total tasks, maximum task time, number of threads, * (optional) "--verbose" for verbose output * * Parallel version with static assignment of tasks to threads. */ public class MasterWorkerParStatic { /* variables to be used by all threads */ private int numThreads; private List taskList; private boolean verbose = false; private int totalTaskTime = 0; private int minThreadTotalTaskTime; private int maxThreadTotalTaskTime; /** * Main method. */ public static void main(String[] args) { String usageMessage = "parameters: numTasks maxTaskTime numThreads [--verbose]"; final int REQUIRED_PARMS = 3; int numTasks = 0; int maxTaskTime = 0; int numThreads = 0; boolean verbose = false; /* process command-line arguments */ if (args.length < REQUIRED_PARMS) { System.err.println(usageMessage); System.exit(1); } try { numTasks = Integer.parseInt(args[0]); maxTaskTime = Integer.parseInt(args[1]); numThreads = Integer.parseInt(args[2]); } catch (NumberFormatException e) { System.err.println(usageMessage); System.exit(1); } if (args.length > REQUIRED_PARMS) { if (args[REQUIRED_PARMS].equals("--verbose")) verbose = true; else { System.err.println(usageMessage); System.exit(1); } } /* do processing */ new MasterWorkerParStatic(numTasks, maxTaskTime, numThreads, verbose); } /** Constructor (actually where processing occurs too). */ public MasterWorkerParStatic(int numTasks, int maxTaskTime, int _numThreads, boolean _verbose) { numThreads = _numThreads; verbose = _verbose; maxThreadTotalTaskTime = 0; minThreadTotalTaskTime = maxTaskTime * numTasks; /* start timing */ long startTime = System.currentTimeMillis(); /* build list of tasks */ taskList = FakeTasks.randomTasks(numTasks, maxTaskTime); /* create threads */ Thread[] threads = new Thread[numThreads]; for (int i = 0; i < threads.length; ++i) { threads[i] = new Thread(new Worker(i)); } /* start them up */ for (int i = 0; i < threads.length; ++i) { threads[i].start(); } /* wait for them to finish */ for (int i = 0; i < threads.length; ++i) { try { threads[i].join(); } catch (InterruptedException e) { System.err.println("this should not happen"); e.printStackTrace(); } } /* end timing and print result */ long endTime = System.currentTimeMillis(); System.out.printf("\nthreaded parallel version with %d threads" + ", static assignment of tasks\n", numThreads); System.out.printf("number of tasks = %d\n", numTasks); System.out.printf("max task time = %d\n", maxTaskTime); System.out.printf("total task time = %d\n", totalTaskTime); System.out.printf("total task time in threads ranges from %d to %d\n", minThreadTotalTaskTime, maxThreadTotalTaskTime); System.out.printf("running time = %g\n", (double) (endTime - startTime) / 1000); } /* methods for use by threads */ /** * Update global variables at end of thread. */ private synchronized void updateGlobals(int threadTotalTaskTime) { maxThreadTotalTaskTime = Math.max(maxThreadTotalTaskTime, threadTotalTaskTime); minThreadTotalTaskTime = Math.min(minThreadTotalTaskTime, threadTotalTaskTime); totalTaskTime += threadTotalTaskTime; } /** * Class to contain code to run in each thread. */ private class Worker implements Runnable { private int myID; private int threadNumTasks = 0; private int threadTotalTaskTime = 0; public Worker(int ID) { myID = ID; } public void run() { int count = 0; /* * mimic MPI version of this example -- each thread examines * all tasks but only processes its assigned ones (where the * assignment is round-robin style) */ for (FakeTasks.Task t : taskList) { if (((count++) % numThreads) == myID) { ++threadNumTasks; threadTotalTaskTime += t.time; FakeTasks.TaskResult tr = t.execute(); if (verbose) { System.out.printf("(thread %d) %s\n", myID, FakeTasks.toString(t, tr)); } } } System.out.printf( "thread %d number of tasks = %d, total time = %d\n", myID, threadNumTasks, threadTotalTaskTime); /* thread-safe update to globals */ updateGlobals(threadTotalTaskTime); } } }