From the tutorial , it's a little different.
In C, when the fork is done, you have 2 processes, one parent and one child. Given the child's pid, the parent process can join when the child process ends.
In Java, the algorithm is similar, but the operation for the Operating System is different. The algorithm is
se (a parte de trabalho for pequena o suficiente)
faça o que tem que fazer
caso contrário
divida o meu trabalho em duas partes
execute as duas partes e espere pelo resultado
Example taken from University of Washington :
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
class Sum extends RecursiveTask<Long> {
static final int SEQUENTIAL_THRESHOLD = 5000;
int low;
int high;
int[] array;
Sum(int[] arr, int lo, int hi) {
array = arr;
low = lo;
high = hi;
}
protected Long compute() {
if(high - low <= SEQUENTIAL_THRESHOLD) {
long sum = 0;
for(int i=low; i < high; ++i)
sum += array[i];
return sum;
} else {
int mid = low + (high - low) / 2;
Sum left = new Sum(array, low, mid);
Sum right = new Sum(array, mid, high);
left.fork();
long rightAns = right.compute();
long leftAns = left.join();
return leftAns + rightAns;
}
}
static long sumArray(int[] array) {
return ForkJoinPool.commonPool().invoke(new Sum(array,0,array.length));
}
}
In this example, you make a sum of the elements of an Array. If the array has more than 5000 elements, the task is split. The compute
method implements the described pseudo-code.
Sort example :
static class SortTask extends RecursiveAction {
final long[] array; final int lo, hi;
SortTask(long[] array, int lo, int hi) {
this.array = array; this.lo = lo; this.hi = hi;
}
SortTask(long[] array) { this(array, 0, array.length); }
protected void compute() {
if (hi - lo < THRESHOLD)
sortSequentially(lo, hi);
else {
int mid = (lo + hi) >>> 1;
invokeAll(new SortTask(array, lo, mid),
new SortTask(array, mid, hi));
merge(lo, mid, hi);
}
}
// implementation details follow:
static final int THRESHOLD = 1000;
void sortSequentially(int lo, int hi) {
Arrays.sort(array, lo, hi);
}
void merge(int lo, int mid, int hi) {
long[] buf = Arrays.copyOfRange(array, lo, mid);
for (int i = 0, j = lo, k = mid; i < buf.length; j++)
array[j] = (k == hi || buf[i] < array[k]) ?
buf[i++] : array[k++];
}
}
First you have to choose the type of Task
. There are two options:
-
RecusiveTask
: returns a result after fork
-
ActionTask
: does not return a result after fork
Second you have to implement the compute method following the pseudo-algorithm, using invokeAll
, compute
, fork
and join
.
Finally, you have to use a thread pool called ForkJoinPool
. I have seen at least two ways:
ForkJoinPool.commonPool().invoke(task);
or
ForkJoinPool pool = new ForkJoinPool();
pool.invoke(task);
At the bottom of the screen, java.util.Arrays.parallelSort uses Fork / Join API.