// // Program to add numbers (read in from file, or generated // randomly). // // Command-line arguments: // (1) number of threads to use (P) // (2) name of file containing numbers (doubles) // or "-n N" to randomly generate N doubles. // import java.text.*; // has NumberFormat import java.util.*; // has Vector, Random // ---- Class containing main program -------------------------------- public class ThreadsSum1 { // ---- Static variables (for use by all threads) ---------------- private static int P; // number of threads private static double[] nums; // numbers to add // (count in nums.length) private static double sum; // ---- Main program --------------------------------------------- public static void main(String[] args) { if (args.length < 2) { System.err.println("Usage: java ThreadsSum1 " + "numThreads [inputfile | -n N]"); System.exit(1); } P = Integer.parseInt(args[0]); if (args.length == 2) getFileInput(args[1]); else getRandomInput(Integer.parseInt(args[2])); double startTime = Timer.elapsedSeconds(); // Create threads. Thread[] threads = new Thread[P]; for (int i = 0; i < P; i++) threads[i] = new Thread(new SumObj(i)); // Initialize sum. sum = 0.0; // Start up the threads. for (int i = 0; i < P; i++) threads[i].start(); // Wait for them to finish. for (int i = 0; i < P; i++) { try { threads[i].join(); } catch (InterruptedException e) { } } // Print result. NumberFormat nf = NumberFormat.getInstance(); // set up to print "sum" in fixed-point // (not exponential) integer format. nf.setMaximumFractionDigits(4); System.out.println("Sum = " + nf.format(sum)); double endTime = Timer.elapsedSeconds(); System.out.println("Elapsed time (seconds) = " + Timer.format(endTime - startTime)); } // ---- Methods for use by main program -------------------------- // Get input from file. private static void getFileInput(String filename) { SimpleReader infile = null; try { infile = new SimpleReader(filename); } catch (SimpleReaderIOException e) { System.err.println("Input file " + filename + " not found"); System.exit(1); } Vector vTemp = new Vector(); try { while (true) // loop ends on EOF exception vTemp.add(new Double(infile.readDouble())); } catch (SimpleReaderIOException e) { } nums = new double[vTemp.size()]; for (int i = 0; i < nums.length; ++i) nums[i] = ((Double) vTemp.elementAt(i)).doubleValue(); } // Generate (pseudo)random input. // Uses the same seed every time so answer does not depend on number // of threads. private static void getRandomInput(int n) { nums = new double[n]; Random generator = new Random(1); for (int i = 0; i < nums.length; ++i) nums[i] = generator.nextDouble(); } // ---- Methods for use by threads ------------------------------- // Add partial sum to global sum. // Note use of "synchronized" keyword to ensure that only one // thread at a time can access this shared variable. private synchronized static void addToSum(double d) { // System.out.println("partial sum = " + d); sum += d; } // ---- Inner class to contain data and code for each thread ----- static class SumObj implements Runnable { private int id; public SumObj(int id) { this.id = id; } // Generally, run() defines behavior of thread. // Here, it computes the partial sum of N/P of the elements // and adds it to the sum. public void run() { double partialSum = 0.0; int N = nums.length; int numsPerThread = (N + P - 1) / P; int first = id * numsPerThread; int limit = first + numsPerThread; if (limit > N) limit = N; for (int i = first; i < limit; ++i) partialSum += nums[i]; addToSum(partialSum); } } }