- [Instructor] The Fork/Join framework functions
based on four main classes, ForkJoinPool,
ForkJoinTask, RecursiveAction, and RecursiveTask.
ForkJoinPool is the core of the framework.
It is what facilitates effective parallel execution
of tasks by making use of the work-stealing algorithm.
It's a special thread pool that manages worker threads.
By the way, worker threads are nothing
but threads that run tasks or subtasks.
The ForkJoinPool is defined
in the java.util.concurrentpackage
and is a specialized implementation
of the ExecutorService interface.
So it can be thought of as an ExecutorService
for running Fork/Join tasks.
What is a Fork/Join task?
We'll come to it next.
There are many methods in this class,
but let's look at a few important methods here.
These three methods execute, invoke, and submit
are used to submit Fork/Join tasks
into the Fork/Join Pool,
by non Fork/Join task clients such as the main thread.
For instance, in the main method of your program,
you would call any
of these methods on your Fork/Join pool instance.
By the way, a non Fork/Join task client could be any part
of the program that submits Fork/Join tasks from outside
to the Fork/Join pool.
When any of these methods are called,
the task goes into a shared global queue.
Execute puts a non-value returning Fork/Join task
for asynchronous execution.
Invoke performs the given Fork/Join task,
returning results upon completion.
This call is synchronous.
Submit submits a Fork/Join task for execution.
Execute and submit as other overloads,
but here we are focusing on the methods
that take a Fork/Join task as an argument.
Static ForkJoinPool.commonPool() method is a factory method
that returns an instance of the default thread pool
for every Fork/Join task.
In most cases, using this default pool is recommended,
but it's also possible to create a custom pool using one
of the Fork/Join pool constructors.
ForkJoinTask is an abstract representation of a task
that can run within a Fork/Join pool.
In simple terms,
just as how they execute a service would execute task
of type runnable and callable,
the Fork/Join pool executes task of type Fork/Join task.
These are lightweight and a huge number of them can be run
by a small number of worker threads in a Fork/Join pool
ForkJoinTask has a few important methods,
fork() that submits the task
to execute asynchronously and return it.
Join() that waits until the task is done
and returns the result, and invoke(),
that combines fork() and join() in a single call.
It starts the task, waits for it to end,
and returns the result.
The static method invokeAll(), and its overloads,
not only combines the fork() and join() functions,
but also invokes more than one task at a time.
RecursiveAction and RecursiveTask are two subclasses
of the abstract base ForkJoinTask class.
RecursiveAction represents a task
that doesn't return any value, similar to runnable.
RecursiveTask represents a task
that returns a value or a result similar to callable.
You'll be inheriting from one of them.
RecursiveAction and RecursiveTask
both have an abstract compute method.
When you inherit either,
you should provide an implementation for this method.
The compute() method
in RecursiveAction doesn't return anything while the one
in RecursiveTask can return any type of value.
The logic implemented would typically follow this pseudocode
where we write code for, fork, computation, and join steps.
So the first block is where the task is split recursively.
That was a quick look at the important classes
and the methods of the Fork/Join framework.