Home » Java » Core Java » Java 7: Fork/Join Framework Example

About Fahd Shariff

Fahd Shariff
Fahd is a software engineer working in the financial services industry. He is passionate about technology and specializes in Java application development in distributed environments.

Java 7: Fork/Join Framework Example

The Fork/Join Framework in Java 7 is designed for work that can be broken down into smaller tasks and the results of those tasks combined to produce the final result. In general, classes that use the Fork/Join Framework follow the following simple algorithm:
 
 
 
 
 
 
 

// pseudocode
Result solve(Problem problem) {
  if (problem.size < SEQUENTIAL_THRESHOLD)
    return solveSequentially(problem);
  else {
    Result left, right;
    INVOKE-IN-PARALLEL {
      left = solve(extractLeftHalf(problem));
      right = solve(extractRightHalf(problem));
    }
    return combine(left, right);
  }
}

In order to demonstrate this, I have created an example to find the maximum number from a large array using fork/join:

import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

public class MaximumFinder extends RecursiveTask<Integer> {

  private static final int SEQUENTIAL_THRESHOLD = 5;

  private final int[] data;
  private final int start;
  private final int end;

  public MaximumFinder(int[] data, int start, int end) {
    this.data = data;
    this.start = start;
    this.end = end;
  }

  public MaximumFinder(int[] data) {
    this(data, 0, data.length);
  }

  @Override
  protected Integer compute() {
    final int length = end - start;
    if (length < SEQUENTIAL_THRESHOLD) {
      return computeDirectly();
    }
    final int split = length / 2;
    final MaximumFinder left = new MaximumFinder(data, start, start + split);
    left.fork();
    final MaximumFinder right = new MaximumFinder(data, start + split, end);
    return Math.max(right.compute(), left.join());
  }

  private Integer computeDirectly() {
    System.out.println(Thread.currentThread() + ' computing: ' + start
                       + ' to ' + end);
    int max = Integer.MIN_VALUE;
    for (int i = start; i < end; i++) {
      if (data[i] > max) {
        max = data[i];
      }
    }
    return max;
  }

  public static void main(String[] args) {
    // create a random data set
    final int[] data = new int[1000];
    final Random random = new Random();
    for (int i = 0; i < data.length; i++) {
      data[i] = random.nextInt(100);
    }

    // submit the task to the pool
    final ForkJoinPool pool = new ForkJoinPool(4);
    final MaximumFinder finder = new MaximumFinder(data);
    System.out.println(pool.invoke(finder));
  }
}

The MaximumFinder class is a RecursiveTask which is responsible for finding the maximum number from an array. If the size of the array is less than a threshold (5) then find the maximum directly, by iterating over the array. Otherwise, split the array into two halves, recurse on each half and wait for them to complete (join). Once we have the result of each half, we can find the maximum of the two and return it.
 

Reference: Java 7: Fork/Join Framework Example from our JCG partner Fahd Shariff at the fahd.blog blog.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!

 

1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design

 

and many more ....

 

Receive Java & Developer job alerts in your Area

 

Leave a Reply

4 Comments on "Java 7: Fork/Join Framework Example"

Notify of
avatar
Sort by:   newest | oldest | most voted
Manoj
Guest
In the compute api, instead of calling compute() api directly on right, we can fork it like below: @Override protected Integer compute() { final int length = end – start; if ( length < SEQUENTIAL_THRESHOLD ) { return computeDirectly(); } final int split = length / 2; final MaximumFinder left = new MaximumFinder( data, start, start + split ); left.fork(); final MaximumFinder right = new MaximumFinder( data, start + split, end ); // return max( right.compute(), left.join() ); // either we can return by calling right.compute(), else call right.fork, and then call max // on right.join and left.join right.fork(); return… Read more »
anonymous
Guest
thanks for your post but i observed following things main purpose of fork/join is to improve performance by running task in parallel, but what i observed that time taken by sequential processing is always better than fork join processing. //code MaximumFinder finderSeq=new MaximumFinder(data); long startTimeSeq=System.nanoTime(); Integer maxValueSeq=finderSeq.computeDirectly(); long endTimeSeq=System.nanoTime(); System.out.println(“Seq Time For execution “+(endTimeSeq-startTimeSeq)+” max value “+maxValueSeq); // submit the task to the pool final ForkJoinPool pool = new ForkJoinPool(4); final MaximumFinder finder = new MaximumFinder(data); long startTimeParallel=System.nanoTime(); Integer maxValueParallel=pool.invoke(finder); long endTimeParallel=System.nanoTime(); System.out.println(“Parallel Time For execution “+(endTimeParallel-startTimeParallel)+” maxValueParallel “+maxValueParallel); //—————– Seq Time For execution 5037392 max value 99 Parallel Time… Read more »
eduardo milpas
Guest

For the guy that mentions the time is the same in sequence and parallel processing:

I’d like to see you implementation, I’ve run many times this example vs a sequential one and my results are:

ARRAY SIZE:1,000,000
max value [99] obtained in 196 millis
seq max value [99] obtained in 6 millis

eduardo milpas
Guest

My guess is that takes more time in parallel due to creation of new instances of MaximumFinder

wpDiscuz