VOOZH about

URL: https://www.javacodegeeks.com/2013/02/java-7-forkjoin-framework-example.html

⇱ 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 ....
I agree to the Terms and Privacy Policy

Thank you!

We will contact you soon.

πŸ‘ Photo of Fahd Shariff
Fahd Shariff
February 18th, 2013Last Updated: February 17th, 2013
4 244 2 minutes read

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.
Subscribe

This site uses Akismet to reduce spam. Learn how your comment data is processed.

4 Comments
Oldest
Newest Most Voted
Manoj
11 years ago

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 Β»

0
Reply
anonymous
9 years ago

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 Β»

0
Reply
eduardo milpas
9 years ago
Reply to  anonymous

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

0
Reply
eduardo milpas
9 years ago
Reply to  anonymous

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

0
Reply
Back to top button
Close
wpDiscuz