Jermain189
Jermain189

Reputation: 35

Java thread manipulation, parallel programming

I am taking an online course on java programming and came across this problem, I am looking at parallel programming using threads.

I am to make a "quad-core" version of a program that calculates pi by dividing the range of the sum into four equal parts, and uses four threads.

I have tried to split it up into 4 different threads and to start and join each thread.

public class quadCorePi extends Thread {

public static void main(String[] args) throws Exception {

          long startTime = System.currentTimeMillis();

          quadCorePi thread1 = new quadCorePi();
          thread1.begin = 0 ;
          thread1.end = numSteps / 4 ;

          quadCorePi thread2 = new quadCorePi();
          thread2.begin = 1 ;
          thread2.end = numSteps / 4 ;

          quadCorePi thread3 = new quadCorePi();
          thread3.begin = 2 ;
          thread3.end = numSteps / 4 ;

          quadCorePi thread4 = new quadCorePi();
          thread4.begin = numSteps / 4 ;
          thread4.end = numSteps ;



          thread1.start();
          thread2.start();
          thread3.start();
          thread4.start();

          thread1.join();
          thread2.join();
          thread3.join();
          thread4.join();

          long endTime = System.currentTimeMillis();

          double pi = step * (thread1.sum + thread2.sum + thread3.sum + thread4.sum);


          System.out.println("Value of pi: " + pi);

          System.out.println("Calculated in " +
                             (endTime - startTime) + " milliseconds");
      }

But it gives me the wrong value for pi, an explanation would be really helpful to how to split the work up for threads.

This was the example code given:

public class ParallelPi extends Thread {

  public static void main(String[] args) throws Exception {

      long startTime = System.currentTimeMillis();

      ParallelPi thread1 = new ParallelPi();
      thread1.begin = 0 ;
      thread1.end = numSteps / 2 ;

      ParallelPi thread2 = new ParallelPi();
      thread2.begin = numSteps / 2 ;
      thread2.end = numSteps ;

      thread1.start();
      thread2.start();

      thread1.join();
      thread2.join();

      long endTime = System.currentTimeMillis();

      double pi = step * (thread1.sum + thread2.sum) ;

      System.out.println("Value of pi: " + pi);

      System.out.println("Calculated in " +
                         (endTime - startTime) + " milliseconds");
  }

  static int numSteps = 10000000;

  static double step = 1.0 / (double) numSteps;

  double sum ;  
  int begin, end ;

  public void run() {

      sum = 0.0 ;

      for(int i = begin ; i < end ; i++){
          double x = (i + 0.5) * step ;
          sum += 4.0 / (1.0 + x * x);
      }
  }
  }

Upvotes: 2

Views: 539

Answers (3)

BarrySW19
BarrySW19

Reputation: 3819

An improvement would be to use the proper Java concurrent libraries - here is how the code would look in that case:

public class ParallelPi implements Callable<Double> {
    private static final ExecutorService executorService = 
            Executors.newFixedThreadPool(4);
    private static final int numSteps = 10000000;
    private static final double step = 1.0 / (double) numSteps;

    private final int begin, end;

    public ParallelPi(int begin, int end) {
        this.begin = begin;
        this.end = end;
    }

    public static void main(String[] args) throws Exception {
        long startTime = System.currentTimeMillis();

        List<Future<Double>> results = executorService.invokeAll(Arrays.asList(
                new ParallelPi(0, numSteps / 4), 
                new ParallelPi(numSteps / 4, numSteps / 2),
                new ParallelPi(numSteps / 2, 3 * numSteps / 4),
                new ParallelPi(3 * numSteps / 4, numSteps)));

        double pi = 0;
        for(Future<Double> result: results) {
            pi += result.get();
        }
        pi *= step;

        long endTime = System.currentTimeMillis();

        System.out.println("Value of pi: " + pi);
        System.out.println("Calculated in " + 
                (endTime - startTime) + " milliseconds");
    }

    @Override
    public Double call() throws Exception {
        double sum = 0.0;

        for (int i = begin; i < end; i++) {
            double x = (i + 0.5) * step;
            sum += 4.0 / (1.0 + x * x);
        }
        return sum;
    }
}

Upvotes: 0

user3248346
user3248346

Reputation:

Your limits are incorrect. Here is the corrected code:

public class QuadCorePi extends Thread {

    public static void main(String[] args) throws Exception {

        long startTime = System.currentTimeMillis();

        QuadCorePi thread1 = new QuadCorePi();
        thread1.begin = 0 ;
        thread1.end = numSteps / 4 ;

        QuadCorePi thread2 = new QuadCorePi();
        thread2.begin = numSteps / 4 ;
        thread2.end =  numSteps  / 2 ;

        QuadCorePi thread3 = new QuadCorePi();
        thread3.begin = numSteps / 2 ;
        thread3.end = 3 * numSteps / 4 ;

        QuadCorePi thread4 = new QuadCorePi();
        thread4.begin = 3 * numSteps / 4 ;
        thread4.end = numSteps ;

        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();

        thread1.join();
        thread2.join();
        thread3.join();
        thread4.join();

        long endTime = System.currentTimeMillis();

        double pi = step * (thread1.sum + thread2.sum + thread3.sum + thread4.sum) ;

        System.out.println("Value of pi: " + pi);

        System.out.println("Calculated in " +
                (endTime - startTime) + " milliseconds");
    }

    static int numSteps = 10000000;

    static double step = 1.0 / (double) numSteps;

    double sum ;
    int begin, end ;

    public void run() {

        sum = 0.0 ;

        for(int i = begin ; i < end ; i++){
            double x = (i + 0.5) * step ;
            sum += 4.0 / (1.0 + x * x);
        }
    }
}

Upvotes: 1

Gregor Ra&#253;man
Gregor Ra&#253;man

Reputation: 3081

Are you sure that the limits for the calculators are ok? Shouldn't it be:

thread2.begin = numSteps / 4 + 1 ;
thread2.end = numSteps / 2;

and so on for 3 and 4?

Upvotes: 0

Related Questions