
import java.util.Random;
import java.util.Scanner;

/**
 * Class that demonstrates Java threads for coordination synchronization.
 *
 * @author Dave Reed
 * @version 4/2/19
 */
public class ArraySum {

    /**
     * Calculates the sum of the numbers in the array.
     *
     * @param a the array of numbers
     * @param threadCount the number of separate threads that can be spawned
     * @return the sum of the numbers
     */
    public static int sumConcurrently(int[] a, int threadCount) {
        int len = (int) Math.ceil(1.0 * a.length / threadCount);
        Thread[] threads = new Thread[threadCount];
        for (int i = 0; i < threadCount; i++) {
            threads[i] = new SumThread(a, i * len, Math.min((i + 1) * len, a.length));
            threads[i].start();
        }
        try {
            for (Thread t : threads) {
                t.join();
            }
        } catch (InterruptedException ie) {
        }

        int total = 0;
        for (Thread summer : threads) {
            total += ((SumThread) summer).getSum();
        }
        return total;
    }

    ////////////////////////////////////////////////////////////////////////
    
    public static void main(String[] args) {
        Random randy = new Random();
        int size = 1000;

        System.out.println("Enter number of threads: ");
        Scanner input = new Scanner(System.in);
        int numThreads = input.nextInt();
        input.close();

        while (true) {
            int[] nums = new int[size];
            for (int j = 0; j < size; j++) {
                nums[j] = randy.nextInt();
            }

            long startTime1 = System.currentTimeMillis();
            int total = 0;
            for (int j = 1; j <= 1000; j++) {
                total = sumConcurrently(nums, numThreads);
            }
            long endTime1 = System.currentTimeMillis();

            System.out.printf("%10d elements  =>  %6d microsec \n", size, endTime1 - startTime1);
            size *= 2;
        }
    }

}
