/** * 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, seed, threads, * (optional) "--verbose" for verbose output * * Multithreaded version with dynamic assignment of tasks to threads. */ package csci3366.sample.masterworker.threads; import java.util.List; import java.util.ArrayList; import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import csci3366.sample.masterworker.FakeTasks; public class MasterWorkerParDynamic { /* variables to be used by all threads */ private static boolean verbose = false; private static int numThreads = 0; private static FakeTasks.SynchTaskQueue taskQueue; /** * Main method. */ public static void main(String[] args) { String usageMessage = "parameters: numTasks maxTaskTime seed numThreads [--verbose]"; int numTasks = 0; int maxTaskTime = 0; int seed = 0; /* process command-line arguments */ if (args.length < 4) { System.err.println(usageMessage); System.exit(1); } try { numTasks = Integer.parseInt(args[0]); maxTaskTime = Integer.parseInt(args[1]); seed = Integer.parseInt(args[2]); numThreads = Integer.parseInt(args[3]); } catch (NumberFormatException e) { System.err.println(usageMessage); System.exit(1); } if (args.length > 4) { if (args[4].equals("--verbose")) verbose = true; else { System.err.println(usageMessage); System.exit(1); } } int totalTaskTime = 0; int maxThreadTotalTaskTime = 0; int minThreadTotalTaskTime = maxTaskTime * numTasks; /* start timing */ long startTime = System.currentTimeMillis(); /* build queue of tasks */ taskQueue = new FakeTasks.SynchTaskQueue(FakeTasks.randomTasks( numTasks, maxTaskTime, seed)); /* create executor for threads */ ExecutorService executor = Executors.newFixedThreadPool(numThreads); /* * create tasks (that return total task time in thread) * and send to executor, creating Future objects so we can wait for * tasks to finish (and get the returned values) */ List> times = new ArrayList>(); for (int i = 0; i < numThreads; ++i) { times.add(executor.submit(new Worker(i))); } /* shut down executor and wait for threads to finish */ executor.shutdown(); for (Future t : times) { try { int threadTotalTaskTime = t.get(); maxThreadTotalTaskTime = Math.max(maxThreadTotalTaskTime, threadTotalTaskTime); minThreadTotalTaskTime = Math.min(minThreadTotalTaskTime, threadTotalTaskTime); totalTaskTime += threadTotalTaskTime; } catch (ExecutionException e) { System.err.println("should not happen"); } catch (InterruptedException e) { System.err.println("should not happen"); } } /* end timing and print result */ long endTime = System.currentTimeMillis(); System.out.printf("\nthreaded parallel version with %d threads" + ", dynamic 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); } /** * Class to contain code to run in each thread. */ private static class Worker implements Callable { private int myID; private int threadNumTasks = 0; private int threadTotalTaskTime = 0; /** Constructor. */ public Worker(int ID) { myID = ID; } /** Code for thread. Returns total task time. */ public Integer call() { FakeTasks.Task t = null; /* get tasks from queue until queue is empty */ while ((t = taskQueue.get()) != null) { ++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 task time = %d\n", myID, threadNumTasks, threadTotalTaskTime); return new Integer(threadTotalTaskTime); } } }