Saturday, December 10, 2011

How to do parallel processing in java?

I have this question in my mind for long time. We have dual processor/multi processor whether we are using the full power of those. How JVM itself can split the task across the processor and make the instruction set execution more efficient?

As usual before I move 5 steps in my thought process, industry will move 50 steps. No wonder, we have solve for this in Java 7.

It's the fork/join framework is an implementation of the ExecutorService interface that helps you take advantage of multiple processors. As with any ExecutorService, the fork/join framework distributes tasks to worker threads in a thread pool. The fork/join framework is distinct because it uses a work-stealing algorithm. Worker threads that run out of things to do can steal tasks from other threads that are still busy.

 If you are not using Java 7 you also need to have "jsr166y.jar" in the classpath.
package com.sarav.forkjoin;

import java.util.Random;

public class Problem {
private final int[] list = new int[2000000]; public Problem() { Random generator = new Random(19580427); for (int i = 0; i < list.length; i++) { list[i] = generator.nextInt(500000); } } public int[] getList() { return list; } }
RecrusiveAction implementation
package com.sarav.forkjoin;

import java.util.Arrays;

import jsr166y.forkjoin.RecursiveAction;

public class Solver extends RecursiveAction {
 private int[] list;
 public long result;

 public Solver(int[] array) {
  this.list = array;
 }

 @Override
 protected void compute() {
  if (list.length == 1) {
   result = list[0];
  } else {
   int midpoint = list.length / 2;
   int[] l1 = Arrays.copyOfRange(list, 0, midpoint);
   int[] l2 = Arrays.copyOfRange(list, midpoint, list.length);
   Solver s1 = new Solver(l1);
   Solver s2 = new Solver(l2);
   forkJoin(s1, s2);
   result = s1.result + s2.result;
  }
 }
}
Test to verify my understanding
package com.sarav.forkjoin.testing;

import jsr166y.forkjoin.ForkJoinExecutor;
import jsr166y.forkjoin.ForkJoinPool;
import com.sarav.forkjoin.Problem;
import com.sarav.forkjoin.Solver;

public class Test {

 public static void main(String[] args) {
  Problem test = new Problem();
  // Check the number of available processors
  int nThreads = Runtime.getRuntime().availableProcessors();
  System.out.println(nThreads);
  Solver mfj = new Solver(test.getList());
  ForkJoinExecutor pool = new ForkJoinPool(nThreads);
  pool.invoke(mfj);
  long result = mfj.getResult();
  System.out.println("Done. Result: " + result);
  long sum = 0;
  // Check if the result was ok
  for (int i = 0; i < test.getList().length; i++) {
   sum += test.getList()[i];
  }
  System.out.println("Done. Result: " + sum);
 }
}


I didn't apply this in my real time application to give some performance report. Soon I will :)