public class MultithreadMean { private static final String IDENT_PATTERN = "Multithreaded computation example: %s\n"; private static final String INIT_DATA_PATTERN = "Initializing data "; private static final String INIT_THREADS_PATTERN = "Initializing %d threads "; private static final String TIME_PATTERN = "(%d ms)\n"; private static final String PROCESS_PATTERN = "Processing data\n"; private static final String RESULT_PATTERN = "\tCount = %d\n\tArithmetic mean = %f\n\tGeometric mean = %f\n"; private static final int ARRAY_SIZE = 10000000; private static final int RANDOM_SEED = 20110523; private static final int NUM_THREADS = 4; private byte[] values; private int count; private long sum; private double logSum; private Worker[] workers; public static void main(String[] args) { MultithreadMean manager = new MultithreadMean(); System.out.printf(IDENT_PATTERN, "Race Condition"); manager.initializeData(); manager.initializeThreads(); manager.process(); } private void initializeData() { long start = System.currentTimeMillis(); java.util.Random rng = new java.util.Random(RANDOM_SEED); System.out.printf(INIT_DATA_PATTERN); values = new byte[ARRAY_SIZE]; for (int i = 0; i < values.length; i++) { values[i] = (byte) (1 + rng.nextInt(Byte.MAX_VALUE)); } count = 0; sum = 0; logSum = 0; System.out.printf(TIME_PATTERN, System.currentTimeMillis() - start); } private void process() { long start = System.currentTimeMillis(); System.out.printf(PROCESS_PATTERN); processWithThreads(); System.out.printf(RESULT_PATTERN, count, sum / (double) count, Math.exp(logSum / count)); System.out.printf(TIME_PATTERN, System.currentTimeMillis() - start); } private void initializeThreads() { long start = System.currentTimeMillis(); int sliceLength = values.length / NUM_THREADS; System.out.printf(INIT_THREADS_PATTERN, NUM_THREADS); workers = new Worker[NUM_THREADS]; for (int i = 0; i < workers.length; i++) { workers[i] = new Worker(sliceLength * i, sliceLength); } System.out.printf(TIME_PATTERN, System.currentTimeMillis() - start); } private void processWithThreads() { for (int i = 0; i < workers.length; i++) { workers[i].start(); } for (int i = 0; i < workers.length; i++) { try { workers[i].join(); } catch (InterruptedException e) {} } } public void update(byte value) { sum += value; logSum += Math.log(value); count++; } private class Worker extends Thread { private int rangeStart; private int rangeLength; public Worker(int rangeStart, int rangeLength) { this.rangeStart = rangeStart; this.rangeLength = rangeLength; } public void run() { for (int i = rangeStart; i < rangeStart + rangeLength; i++) { update(values[i]); } } } }