Fork-join operation process
As follows:
The parallel execution framework fork-Join in the JDK uses a “work-stealing” algorithm, where a thread steals tasks from another queue to execute them.
2. Fork-join can be implemented in two steps:
Step 1: Divide tasks
Divide large tasks into subtasks, and if the subtasks are not small enough, continue to divide until the subtasks are small enough.
The following two classes are typically inherited to implement their Compute methods.
- RecursiveAction executes a task that returns no value and executes only once.
- RecursiveTask executes a task that returns a value.
Step 2: Execute the task and return the result
Tasks are performed through ForkJoinPool.
Third, the sample
Use fork-join to find the sum of a multi-billionth Integer array
import java.util.Random; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask; /** * An array sum of billions of bytes of Integer data. * Created on 2020-5-24 */ public class ArrayCountTask extends RecursiveTask<Long> { private final int start, end; private static final int grain = 100000; private final int[] data; public ArrayCountTask(int start, int end, int[] data) { this.start = start; this.end = end; this.data = data; } @Override protected Longcompute() {
long count = 0;
if (end - start <= grain) {
for(int i = start; i < end; i++) { count += data[i]; }}else {
int middle = (start + end) >>> 1;
RecursiveTask left = new ArrayCountTask(start, middle, data);
RecursiveTask right = new ArrayCountTask(middle, end, data);
invokeAll(left, right);
long leftJoin = (long) left.join();
long rightJoin = (long) right.join();
count = leftJoin + rightJoin;
}
return count;
}
public static void main(String[] args) {
int total = 500000000;
int[] data = new int[total];
for (int i = 0; i < total; i++) {
data[i] = new Random().nextInt(5);
}
long startTime = System.currentTimeMillis();
long sum = 0;
for (int i = 0; i < total; i++) {
sum += data[i];
}
System.out.println("The result of the ordinary calculation: sum =" + sum);
System.out.println("Time:" + (System.currentTimeMillis() - startTime));
ArrayCountTask task = new ArrayCountTask(0, data.length, data);
ForkJoinPool pool = new ForkJoinPool();
startTime = System.currentTimeMillis();
sum = pool.invoke(task);
System.out.println(ForkJoin: sum =" + sum);
System.out.println("Time:"+ (System.currentTimeMillis() - startTime)); }}Copy the code
Calculation results: