package csci3366sample.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 csci3366sample.ThreadUtility; import csci3366sample.masterworker.FakeTasks; /** * 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, * (optional) "--verbose" for verbose output * * Environment variable NUM_THREADS specifies number of threads. * * Multithreaded version with dynamic assignment of tasks to threads. */ 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 [--verbose]"; final int REQUIRED_PARMS = 2; /* get number of threads from environment variable */ try { numThreads = ThreadUtility.getNumThreads(); } catch (ThreadUtility.Exception e) { System.err.println(e.getMessage()); System.exit(1); } int numTasks = 0; int maxTaskTime = 0; /* 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]); } 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); } } 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)); /* 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); } } }