package com.tutego.insel.thread.concurrent;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;   

public class ArraySummer
{
  /**
   * @param args
   */
  public static void main( String[] args )
  {
    int[] array = new int[ 1000 ];

    Random r = new Random(); 
    for ( int i = 0; i < array.length; i++ )
      array[ i ] = Math.abs( r.nextInt() );

    parallSummer( array );
  }

  public static void parallSummer( int[] array )
  {
    int prozessors = 2; // Runtime.getRuntime().availableProcessors();

    final List<Long> l = new ArrayList<Long>();

    Runnable merger = new Runnable() {
      public void run()
      {
        long sum = 0;
        for ( long i : l )
          sum += i;
        System.out.println( sum );
      }
    };

    CyclicBarrier barrier = new CyclicBarrier( prozessors, merger );

    for ( int part = 0; part < prozessors; part++ )
      new Thread( new AtomarSummer( barrier, array, prozessors, part, l)) .start();
  }
}

class AtomarSummer implements Runnable
{
  private final CyclicBarrier barrier;
  private final int[]         array;
  private final List<Long> l;
  private int                 start, end;

  public AtomarSummer( CyclicBarrier barrier, int[] array, int maxPart, int currentPart, List<Long> l )
  {
    this.barrier = barrier;
    this.array = array;
    this.l = l;

    start = (int) ((double) array.length / maxPart * currentPart);
    end   = (int) ((double) array.length / maxPart * (currentPart + 1) - 1);
  }

  public void run()
  {
    long sum = 0;

    for ( int i = start; i < end; i++ )
      sum += array[ i ];

    l.add( sum );

    try
    {
      barrier.await();
    }
    catch ( InterruptedException e )
    {
      e.printStackTrace();
    }
    catch ( BrokenBarrierException e )
    {
      e.printStackTrace();
    }
  }
}