Fork Join in Java
Nowadays, systems are launching with multicore processors. The multicore processors make the computation faster. Hence, it becomes necessary for a programmer to use multicore processors effectively so that the result can be generated in less span of time. Fork/Join in Java is used to make use of the cores (brain of CPU that process the instructions) in an efficient manner. The fork/join splits a bigger task into smaller sub-tasks. These sub-tasks are then distributed among the cores. The results of these subtasks are then joined to generate the final result. The splitting of a task and joining the results imitates the divide-and-conquer algorithm. The fork is responsible for splitting the task, and join is responsible for merging the results of the task to generate the final result.
It is worth noting here that various threads that are responsible for the completion of the sub-tasks never sit idle. In fact, they implement the work-stealing algorithm, where an idle thread steals the work from those threads that are busy.
An important point to remember is that one should not be blindly splitting a problem into sub-problems. Splitting a problem into sub-problems has its overhead. If the overhead and the time consumed in solving the sub-problems is greater than solving the problem itself, then one should not be splitting the problem. The limit that makes logical sense to split a problem into subproblem is known as threshold.
Java Fork/Join Program
The following program illustrates the working of the fork/join in Java.
The number 50 is found 5 times.
Explanation: In the code, we have extended the abstract class RecursiveTask. The compute() method of the class contains the computational code. The type parameter <Integer> of the class RecursiveTask determines what type of result is returned. The search task created with the help of the class Recursive class is submitted to the ForkJoinPool. When the invoke() method of the ForkJoinPool class is invoked, the task execution starts. The invoke() method combines the fork() as well as the join() method in the single call, and waits for the task execution to finish, and then returns the result. When the invoke() method is called it splits the task into subtasks.
Java ForkJoinPool Class
The center of the fork/join framework is the ForkJoinPool class. The ForkJoinPool class implements the ExecutorService interface. It also extends the AbstractExecutorService class and implements the work-stealing algorithm.
Methods of ForkJoinPool Class
There are two ways to instantiate the ForkJoinClass.
1) Using the Constructor of the Class
ForkJoinPool(): It is the default constructor of the ForkJoinPool class. It creates a default pool. The generated pool supports parallelism that is equal to the total number of processors available in the system. In the above example, we have used this constructor to instantiate the ForkJoinPool class.
ForkJoinPool(int p): It is parameterized constructor that is also used to create a pool with customized parallelism. The value p must be a natural number (> 0) and should not exceed the number of processors available in the system.
2) Using the Static Method commonPool()
The static method commonPool() of the ForkJoinPool class can also be used to create an instance of the ForkJoinPool class.
Total Number of available cores in the system processor is: 4 Total number of active threads before invoking: 0 Total number of active threads after invoking: 3 The size of the Common Pool is: 3