Fork and Join Framework

  1. Available from Java 7
  2. ForkJoin Pool is a kind of executor service for ForkJoin task
  3. It differs from Executor service by virtue of employing Work-stealing i.e if a worker thread has no task in its pipeline then it will take the task from the task queue of the other busy thread so that the work load is efficiently balanced.
  4. To access the pool
    ForkJoinPool pool = ForkJoinPool.commonPool();
    A static common pool is available for the application and it can be accessed through common pool method.
  5. Creating a new pool
    ForkJoinPool pool = new ForkJoinPool();
  6. The primary thought process behind Fork Join is that each task is recursively split into sub task and executed in parallel using fork method where as the join method will wait for the completion of the task and combines the obtained result.
  7. ForkJoinTaks is an Abstract class that implements Future Interface so that we use it extract results once the task is completed.
  8. ForkJoinTask abstract class is extended into two other abstract classes RecursiveAction and RecusiveTask. These classes are abstract and when we extend these classes we need to override compute() method.
  9. The major difference between RecursiveTask and RecursiveActioin is that RecursiveAction’s computer method does not return any value where as computer method of RecursiveTask returns a value.

Example : To search an element in an array and find its count

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
import org.apache.commons.lang3.ArrayUtils;

public class SearchDemo {
	public static void main(String[] args) {
		int arr[] = {20, 10, 20, 30, 20, 50, 40, 80, 60, 70, 90, 50, 20};
		System.out.println(ArrayUtils.toString(arr));
		SearchTask task = new SearchTask(arr, 0, arr.length-1, 20);
		ForkJoinPool pool = ForkJoinPool.commonPool();
		int result = pool.invoke(task);
		System.out.println("Total "+result);
	}
}

class SearchTask extends RecursiveTask<Integer> {
	int[] arr;
	int start;
	int end;
	int search;

	SearchTask(int[] arr, int start, int end, int search) {
		System.out.println("New task created for search from position "+start+" to "+end);
		this.arr = arr;
		this.start = start;
		this.end = end;
		this.search = search;
	}

	@Override
	protected Integer compute() {
		int size = end-start+1;
		int count1,count2,count;
		if(size > 3) {
			int mid = (start + end) /2 ;
			SearchTask task1 = new SearchTask(arr,start,mid,search);
			SearchTask task2 = new SearchTask(arr,mid+1,end,search);
			task1.fork();
			task2.fork();
			count1 = task1.join();
			count2 = task2.join();
			count = count1 + count2;
			return count;
		}else {
			return processSearch();
		}
	}

	private Integer processSearch() {
		int count = 0;
		for (int i = start; i <= end; i++) {
			if (arr[i] == search) {
				count++;
			}
		}
		return count;
	}
}

Leave a Comment