We will divide the work of computing the maximum of all values in an array over multiple threads. Each thread will compute the maximum of a subrange and then update a shared max variable and a shared count of completed threads.

When all threads have completed their work, then the main thread is ready to return the result. Your task is to provide an efficient mechanism for finding out when the work is complete. You should use a condition object and call the await method, thereby deactivating the main thread until one of the subsidiary threads has updated the completion count.

Be sure to use the lock when you check whether the completion count has reached the total number of threads.

You will need to deal with the InterruptedException. It is ok to simply return 0 if it is caught.

Complete the following file:


import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class DataSet { /** Constructs an empty data set. */ public DataSet(double[] values) { this.values = values; max = 0; myLock = new ReentrantLock(); completionCondition = myLock.newCondition(); } /** Gets the maximum of the added data. @return the average or 0 if no data has been added */ public double getMaximum() { if (values.length == 0) return 0; max = values[0]; final int THREADS = 10; int size = values.length / THREADS; for (int i = 0; i < THREADS; i++) { Runnable r = new RangeProcessor(i * size, (i + 1) * size); Thread t = new Thread(r); t.start(); } // Wait while the completion count is less than the number of threads, // Use the await method. Do not call sleep. Do not use a "do nothing loop". // TODO: your work here return max; } private class RangeProcessor implements Runnable { public RangeProcessor(int start, int end) { this.start = start; this.end = Math.min(end, values.length); } public void run() { double rangeMax = values[start]; for (int i = start + 1; i < end; i++) rangeMax = Math.max(rangeMax, values[i]); myLock.lock(); try { max = Math.max(max, rangeMax); completionCount++; // TODO: signal that the completion count changed } finally { myLock.unlock(); } } private int start; private int end; } private double[] values; private double max; private int completionCount; private Lock myLock; private Condition completionCondition; // this method is used to check your work public static void main(String[] args) { final int SIZE = 10000000; double[] v = new double[SIZE]; int shift = (int) (Math.random() * SIZE); for (int i = 0; i < SIZE; i++) v[(i + shift) % SIZE] = i; DataSet data = new DataSet(v); double max = data.getMaximum(); System.out.println(max); } }