/* * numerical integration example, as discussed in textbook: * * compute pi by approximating the area under the curve f(x) = 4 / (1 + x*x) * between 0 and 1. * * parallel version using Java and java.util.concurrent. * * number of threads is taken from environment variable NUM_THREADS. */ import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.ArrayList; public class NumIntParObjUtil { /* variables/constants to be used by all threads */ private static final int NUM_STEPS = 100000000; private static final double step = 1.0/(double) NUM_STEPS; private int numThreads; /* main method */ public static void main(String[] args) { /* get number of threads from environment variable */ int numThreads = 0; try { String s = System.getenv("NUM_THREADS"); if (s == null) { numThreads = 1; } else { numThreads = Integer.parseInt(s); } } catch (NumberFormatException e) { System.out.println("non-numeric value for NUM_THREADS"); System.exit(1); } NumIntParObjUtil obj = new NumIntParObjUtil(numThreads); obj.compute(); } /* constructor */ public NumIntParObjUtil(int nThreads) { numThreads = nThreads; } /* method to compute and print pi */ public void compute() { double sum = 0.0; /* start timing */ long startTime = System.currentTimeMillis(); /* create executor for threads */ ExecutorService executor = Executors.newFixedThreadPool(numThreads); /* create tasks (that return partial sums) and send to executor, creating Future objects so we can wait for tasks to finish (and get the returned values */ ArrayList> partialSums = new ArrayList>(); for (int i = 0; i < numThreads; ++i) { partialSums.add(executor.submit(new CodeForThread(i))); } /* shut down executor and wait for threads to finish */ executor.shutdown(); for (Future p : partialSums) { try { sum += p.get(); } catch (ExecutionException e) { System.err.println("should not happen"); } catch (InterruptedException e) { System.err.println("should not happen"); } } /* finish computation */ double pi = sum * step; /* end timing and print result */ long endTime = System.currentTimeMillis(); System.out.println("parallel program results with " + numThreads + " threads:"); System.out.println("pi = " + pi); System.out.println("time to compute = " + (double) (endTime - startTime) / 1000); } /* inner class to contain code to run in each thread */ private class CodeForThread implements Callable { private int myID; public CodeForThread(int myID) { this.myID = myID; } public Double call() { double partsum = 0.0; for (int i=myID; i < NUM_STEPS; i += numThreads) { double x = (i+0.5)*step; partsum = partsum + 4.0/(1.0+x*x); } return new Double(partsum); } } }