Clean • Professional
Modern applications often need to process large amounts of data quickly. To improve performance, Java provides tools that allow programs to execute tasks in parallel using multiple CPU cores.
Two important features used for parallel processing in Java are:
Both features help developers break tasks into smaller parts and execute them simultaneously, which can significantly improve performance when working with large datasets.
The Fork/Join Framework is a framework introduced in Java 7 to support parallel programming.
It works on a simple concept called Divide and Conquer.
Instead of processing a large task sequentially, the framework:
Structure of the image:
Large Task
|
Fork (Split)
/ | \\
Task1 Task2 Task3
| | |
Process in Parallel
\\ | /
Join Results
|
Final Result
This framework is mainly used for CPU-intensive tasks such as:
The Fork/Join framework contains several important classes.

ForkJoinPool is a special thread pool designed to run fork/join tasks.
It manages worker threads and distributes tasks efficiently.
Example:
ForkJoinPool pool = new ForkJoinPool();
The pool automatically uses available processor cores for better performance.
ForkJoinTask is the base class for tasks executed inside the ForkJoinPool.
There are two commonly used subclasses:
RecursiveTask is used when a task returns a result.
Example: calculating the sum of numbers in an array.
Example:
import java.util.concurrent.*;
class SumTask extends RecursiveTask<Integer> {
int[] arr;
int start, end;
SumTask(int[] arr, int start, int end) {
this.arr = arr;
this.start = start;
this.end = end;
}
protected Integer compute() {
if (end - start <= 2) {
int sum = 0;
for (int i = start; i < end; i++) {
sum += arr[i];
}
return sum;
}
int mid = (start + end) / 2;
SumTask left = new SumTask(arr, start, mid);
SumTask right = new SumTask(arr, mid, end);
left.fork();
int rightResult = right.compute();
int leftResult = left.join();
return leftResult + rightResult;
}
}
public class Main {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8};
ForkJoinPool pool = new ForkJoinPool();
SumTask task = new SumTask(arr, 0, arr.length);
int result = pool.invoke(task);
System.out.println("Sum: " + result);
}
}
Output:
Sum: 36
The framework uses a technique called Work Stealing.
If one thread finishes its task early, it can steal work from another thread's queue.
This ensures:
Parallel Streams were introduced in Java 8 as part of the Stream API.
They allow developers to process collections in parallel using multiple threads automatically.
Instead of writing complex multi-threading code, Java internally uses the ForkJoinPool to perform parallel operations.
| Feature | Sequential Stream | Parallel Stream |
|---|---|---|
| Processing Method | Processes elements one by one in a single thread | Processes elements simultaneously using multiple threads |
| Performance | Suitable for small datasets | Better for large datasets and CPU-intensive tasks |
| Thread Usage | Uses one thread | Uses multiple threads from the ForkJoinPool |
| Order of Execution | Maintains predictable order | Order may not always be guaranteed |
| Complexity | Simple and easier to debug | Slightly complex due to parallel execution |
| Resource Usage | Uses less CPU resources | Uses more CPU cores for faster execution |
| Syntax Example | list.stream() | list.parallelStream() |
| Best Use Case | Small collections or tasks where order matters | Large datasets where performance improvement is required |
Example: Calculate the sum of numbers using parallel stream
import java.util.*;
public class ParallelExample {
public static void main(String[] args) {
List<Integer> numbers =
Arrays.asList(1,2,3,4,5,6,7,8,9,10);
int sum = numbers.parallelStream()
.mapToInt(Integer::intValue)
.sum();
System.out.println("Sum: " + sum);
}
}
Output:
Sum: 55
Here Java automatically:
List<String> names = Arrays.asList("A","B","C","D");
names.parallelStream()
.forEach(System.out::println);
The output order may vary because the elements are processed in parallel threads.
Parallel streams are useful when:
Examples:
Parallel streams may not be suitable in certain situations:
Using parallel streams unnecessarily may reduce performance instead of improving it.
| Feature | Fork/Join Framework | Parallel Streams |
|---|---|---|
| Introduction | Introduced in Java 7 | Introduced in Java 8 as part of the Stream API |
| Complexity | More complex to implement because developers manage task splitting and joining | Very simple to use with built-in stream methods |
| Control | Provides full control over thread management and task execution | Provides limited control, handled automatically by Java |
| Usage | Used for custom parallel algorithms and complex computations | Mainly used for processing collections in parallel |
| Internal Mechanism | Uses the Work Stealing Algorithm for efficient task distribution | Internally uses the ForkJoinPool for parallel execution |
The Fork/Join Framework and Parallel Streams in Java provide powerful ways to perform parallel processing and improve application performance. The Fork/Join Framework gives developers full control over task splitting and thread management, making it ideal for complex algorithms.
Parallel Streams, on the other hand, provide a simpler way to process collections in parallel with minimal code.