How does ForkJoinPool help in writing concurrent applications? Please provide a few examples for RecursiveTask and RecursiveAction.

By | March 5, 2023

ForkJoinPool is a specialized implementation of the ExecutorService interface in Java that is designed to help in writing concurrent applications that perform parallel tasks on multiple processors. The ForkJoinPool framework uses a divide-and-conquer approach to parallelism, where a large task is broken down into smaller sub-tasks that can be executed concurrently on multiple processors. The framework also uses a work-stealing algorithm to balance the workload among threads in the pool.

The ForkJoinPool framework provides two main classes for executing parallel tasks: RecursiveTask and RecursiveAction.

  1. RecursiveTask:

RecursiveTask is a subclass of ForkJoinTask that represents a task that returns a result. RecursiveTask is used when the task can be broken down into smaller sub-tasks that can be executed concurrently and the results of these sub-tasks can be combined to produce the final result.

Example: Calculating the sum of an array of integers using RecursiveTask:

import java.util.concurrent.*;

class SumTask extends RecursiveTask<Integer> {
private int[] array;
private int start;
private int end;
public SumTask(int[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}
protected Integer compute() {
if (end – start <= 100) {
int sum = 0;
for (int i = start; i < end; i++) {
sum += array[i];
}
return sum;
} else {
int mid = (start + end) / 2;
SumTask left = new SumTask(array, start, mid);
SumTask right = new SumTask(array, mid, end);
left.fork();
right.fork();
return left.join() + right.join();
}
}
}

In this example, the SumTask class extends RecursiveTask and overrides the compute() method to perform the sum of an array of integers. If the size of the array is less than or equal to 100, the task is executed sequentially, otherwise, the array is divided into two sub-arrays and two new SumTask instances are created to calculate the sum of each sub-array. The left and right tasks are then forked and the result is obtained by calling join() on each task.

  1. RecursiveAction:

RecursiveAction is a subclass of ForkJoinTask that represents a task that does not return a result. RecursiveAction is used when the task can be broken down into smaller sub-tasks that can be executed concurrently, and the results of these sub-tasks are not required to produce the final result.

Example: Sorting an array of integers using RecursiveAction:

import java.util.concurrent.*;

class SortTask extends RecursiveAction {
private int[] array;
private int start;
private int end;
public SortTask(int[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}
protected void compute() {
if (end – start <= 100) {
Arrays.sort(array, start, end);
} else {
int mid = (start + end) / 2;
SortTask left = new SortTask(array, start, mid);
SortTask right = new SortTask(array, mid, end);
left.fork();
right.fork();
left.join();
right.join();
merge(array, start, mid, end);
}
}
private void merge(int[] array, int start, int mid, int end) {
int[] left = Arrays.copyOfRange(array, start, mid);
int[] right = Arrays.copyOfRange(array, mid, end);
int i = 0;

Leave a Reply

Your email address will not be published. Required fields are marked *