Close

Java Fork and Join RecursiveAction Example

[Updated: Oct 14, 2016, Created: Apr 6, 2016]

Java 

Using ForkJoinTask we can subdivide a given task in multiple tasks to run them in parallel in multiple processors.

Following example demonstrate how to use Java 'Fork And Join' RecursiveAction.

ForkJoinPool.commonPool() creates the common pool instance of ForkJoinPool with parallelism equal to Runtime.availableProcessors()

ForkJoinPool.invoke(ForkJoinTask<T> task) performs the given task (in our example we are using subclass of ForkJoinTask: RecursiveAction). This method blocks and only returns upon completion.

RecursiveAction: A recursive ForkJoinTask subclass, which doesn't return any results.

ForkJoinTask<V>.fork(): This method executes the task asynchronously in the pool the current task is running in.

ForkJoinTask<V>.join(): This method blocks until the result of the computation is done.


package com.logicbig.example;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;

public class FileSearchTask extends RecursiveAction {
static long count;

private final File file;

public FileSearchTask (File file) {
this.file = file;
}

@Override
protected void compute () {
List<FileSearchTask> tasks = new ArrayList<>();
File[] files = file.listFiles();
if (files != null)
for (File f : files) {
if (f.isDirectory()) {
FileSearchTask newTask = new FileSearchTask(f);
tasks.add(newTask);
newTask.fork();
} else if (f.getName().endsWith(".java")) {
System.out.println(f.getAbsolutePath());
count++;
}
}
if (tasks.size() > 0) {
for (FileSearchTask task : tasks) {
task.join();
}
}
}

public static void main (String[] args) {
long time = System.currentTimeMillis();
FileSearchTask fileSearchTask = new FileSearchTask(new File("d:\\"));
ForkJoinPool.commonPool().invoke(fileSearchTask);
System.out.println("time taken : "+(System.currentTimeMillis()-time));
}
}


Also try the following code without parallelism and notice the difference. The time elapsed is about twice on my machine.

package com.logicbig.example;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;

public class FileSearchTaskWithoutParallelism extends RecursiveAction {
static long count;

private final File file;

public FileSearchTaskWithoutParallelism (File file) {
this.file = file;
}

@Override
protected void compute () {
//List<FileSearchTaskWithoutParallelism> tasks = new ArrayList<>();
File[] files = file.listFiles();
if (files != null)
for (File f : files) {
if (f.isDirectory()) {
FileSearchTaskWithoutParallelism newTask =
new FileSearchTaskWithoutParallelism(f);
// tasks.add(newTask);
newTask.compute();
} else if (f.getName().endsWith(".java")) {
System.out.println(f.getAbsolutePath());
count++;
}
}
/*if (tasks.size() > 0) {
for (FileSearchTaskWithoutParallelism task : tasks) {
task.join();
}
}*/
}

public static void main (String[] args) {
long time = System.currentTimeMillis();
FileSearchTaskWithoutParallelism fileSearchTask =
new FileSearchTaskWithoutParallelism(new File("d:\\"));
ForkJoinPool.commonPool().invoke(fileSearchTask);
System.out.println("time taken : "+(System.currentTimeMillis()-time));
}
}

See Also