Hello there, students, in this lesson, we are going to learn with your fork join framework, we'll
start from the high level overview of your framework and understanding of its basic principles.
One will understand the theory of Forkin and Journey.
We would jump straight to the source code to learn first joint pool class.
I've explained what works to an algorithm is after that we are going to have practical code examples
and I will show you how to submit tasks for execution with the help of furniture and pool will review
recursive action and recursive type tasks.
And at the end of the lesson we are going to discuss drawbacks of Thorbjoern framework that we need
to be aware of for making a decision about its usage.
Let's start from understanding what Furbies during the framework is.
The first time it was presented in Java version seven.
Why it was needed.
The framework helps to speed up parallel processing by using all available course.
It is designed for work that can be broken into smaller pieces recursively.
The goal is to use all the available processing power to enhance the performance of your application.
Why it is called for joins and it is named after the way how it works.
The Framework X recursively breaking the task into smaller independent subtasks until they're simple
enough to be executed asynchronously.
And after that result of all subtasks, I recursively journey into a single result.
This is due in part.
That's why the framework is called for.
Join the Fork.
Join Framework distributes tasks to various threads in the thread.
Pull workers that are sleeping or waiting, not actually sleeping and waiting.
They're working on other smaller tasks for joint users work stealing algorithm workers.
Threads that run out of things to do can steal tasks from other threats that are still busy.
For example, doesn't create a separate thread for every single subtask.
Instead, each threatened ZAPU has its own double ended.
Q Modak, which stauss tasks.
Let's talk a little bit more about work.
Stulen algorithm.
If I could add a simple thread that if we try to steal work from decks of business threats by default,
every threat gets tasks from the head of its own deck.
When it is empty, the threat takes that task from the tail of the deck of another business threat or
from the global entry queue.
Since this is who has the biggest pieces of work are likely to be located today, we're going to review
a lot of JDK source code and code examples.
So let me start screen sharing.
The center of Fergin framework is, for example, Class I open source code of this class similar to
Oza Executor's.
It extends abasic executive service class that in turn implements executer service allsorts in the CPU
attempt to find and execute tasks submitted to the CPU and or created by other active tasks that that
a blocked or waiting.
At the moment.
This enables efficient processing when most tasks spawn other subtasks, as well as when many small
tasks are submitted to the CPU from external clients.
Let me open now.
For example, demo class I created IT.
Infrastructure and package done for you will be able to find the reference to the source code in attachments
to the lesson.
I am going to walk you through each line in this demo file.
The first thing that we do here is create an offer of joint pull object.
We can do this in different ways.
The first one is to use Static Masset Common Pool.
This will provide a reference to the common pool.
This pool and any ongoing process are automatically terminated upon program termination in case we'll
call X method of system class, for example.
Another way to create an instance of, for example, is just call upon the constructor.
The int parameter describes parallelism level.
This level indicates how many threads or CPUs you want to work concurrently on tasks past the function
pool.
In this case we have parallel is level of four.
We can create four adjourned without passing in value.
In this case, parallelism is equal to the end value that is returned by available processers.
Masset they remember in previous lesson I showed you a verbal processor that we can call on the runtime
object to define the number of processing, of course, we have on the machine.
Basically, if you don't have any specific reasons to set specific level of parallelism, you may use
default constructor.
Also, there is another constructor that allows it to pass to the constructor, sweat factory and error
handler.
Well, would you review similar example?
Also, sweat factory in previous lesson and another argument of type, unquote, exception handler is
a functional interface that requires you to implement logic of handling exceptional cases during the
execution.
It will depend on how you would like to address the exception.
Now we can proceed with submitting a task to our executer, similar to Oprah as examples with Runnable
and Kobel, we can submit two types of tasks actions and tasks.
Action.
This is something one doesn't return any value after execution.
Just set of instructions that needs to be executed in a separate sweat and task.
It is a type that will change the result of the execution similar to callable type.
Recursive action is a type that will not return as a result of the execution and objects of recursive
task type will return result of execution.
Most of them has an absolute mass compute in which the task logic is defined also.
Most of these types extends for the joint task.
Let's review examples with each of these types.
But before we jump to review code example, let me share a basic template for our tasks.
On the slide.
You can see pseudocode.
If my portion of the work is small enough, does it work directly or else split my work into two pieces
in one of the two pieces and wait for the results?
That is how we should implement compute method.
There should be some conditions that will tell us whether we can proceed with the execution directly
or we should create some.
Now let's look at the good example.
So as you may already understand, recursive action is just a set of instructions that are needed to
be done.
And recursive action may still need to break up its work into smaller chunks, which can be executed
by independent threads or CPU's.
Recursive action is an absolute class that extends for joint task.
So to create an object of this type, we need to have concrete implementation of this type in a separate
file of default recursive action clause that extends recursive action.
This is not a very meaningful example, but I decided to keep it super simple in order you would understand
how it works.
We have private in the field with named workload.
We would initialize it with some value during the default recursive action object instantiation.
And here is implementation of our compute method like you saw in template implementation.
On the slide.
We start with definition of a condition that should describe what we are going to proceed with.
Action.
Execution was a threat and one we should split our action into multiple subtasks.
In this case, we check if the workload value is less than 18, 18 in this case is a random threshold.
Just for the sake of example, when workload is less than 18, we just pursued action execution in the
same thread.
But in case it is equal to itchin or more, then we jump to our section where we create subtasks and
call for massive.
Here you can see two alternative ways how to achieve the same result.
We can create subtasks and call for method for each subtask like you can see in the foreach loop.
Or alternatively, we can use for a joint task class and call invoke all method and pass all subtasks
that the result would be the same.
I decided to keep for each loop here because the visualization is better in this case.
Let's understand how we create subtasks basically for our template.
We split my work into two pieces here.
You can see that I create two objects of the same action type and in constructor I pass workload divided
by two.
I add all subtasks to the release and return it from the method.
We use this list and for each loop or in invoke all Masset to submit this action for execution.
Let's get back to the, for example, demo class.
I just create an instance of my default recursive action and I pass it to the constructor.
I call invoke method and pass the reference to my action object.
Let's run this program and you can see that I split the workload and created two subtasks.
To sum it up, in your action task, you need to find a way to reflect the total amount of work.
Also, you need to define suitable thresholds that will be used to split action in subtasks.
Like another example.
This can be separate Masset that knows how to divide the work.
And in implementation of compute method, you should describe the conditions that would define what
it is time to split work into subtasks or proceed with execution.
Hope that it is clear.
Now let's look at the second type of tasks that we can submit into.
For example, now we are going to recursive task, recursive task is also APSA class that extends for
a joint task.
We want to submit a recursive task when we want to get the result of the calculation and the response.
The logic of interaction with objects of this type is similar was on the one difference.
We have to join the results of computation from different set tasks.
Let me open default recursive task class that extends recursive tasks and that implements compute method.
As you can see, we have similar constructor and the same field as we had in recursive action.
In case our condition tells us that we shouldn't split activity in different tasks, we just return
the result.
In this example, we just want to get values that twice the original value in the case.
We need to split our work into subtasks.
We do this, but also we need to join the results of all subtasks.
I call Gern Masset on each subtask that's supposed to return the result of computation.
I aggregate result in one variable and after that I return the result to them.
This case I have, for example, demo two class.
I create an instance of, for example, and call invoke method.
I pass an instance of the false recursive task with workload 40.
I run the program and Incans so output.
You can see that I get 80 as a result.
That is exactly what my task is supposed to do.
Great.
Is it clear for you how the recursive action and recursive task work?
If yes, then we are good to proceed in case the things that are still not clear.
Please leave your question under the switch and I will be happy to answer.
Now we are going to learn more about such factory method from executor's class as new for stealing pool
pull.
This method is overloaded and has versions within parameter and without parameters in the source code
of executor's class.
You can see that this is nothing more than, for example, instantiate that with a specific level of
parallelism or with the default level of parallelism that is equal to the number of available processors
and how to work with.
For example, you already know and we reviewed examples, I believe that you already understood potential
benefits that we expect to get from, for example, effective usage of all course, by splitting tasks
into subtasks, supposed to improve performance.
But we would help us in all cases.
Let's talk about disadvantages of, for example, probably after this lesson, you got an impression
that Fork Join framework is something extremely cool, efficient and super fast.
Probably even started to think that you have to use it.
Most often.
The evolution of Fergin pool vary between different engineers.
Not everyone agreed and shared benefits of this type.
If you would search the Internet pros and cons of, for example, you would discover that a group of
people who doesn't like, for example, because of different reasons on the slide, you can see the
list of the issues and drawbacks of, for example, based on different people opinion.
So it makes sense in some degree and in my opinion, worse to share with you.
So the drawbacks of, for example, are a faulty task manager.
The foraging technique splits the work into fragments and joins the results together.
And some practice that allows an intermediate joint for each fork can only work successfully in a controlled
environment.
A fatal flaw with Fergin framework by opinion of some group of people is that it is trying to manage
and intimidate.
Join in a task outside of a controlled environment.
Only the operating system as c the operating system can manage and intimidate join in the task and usually
there is a problem of errors, exceptions in subsequently FEG tasks.
And the answer to most of the cases that may happen in real life is uncertainty.
But this is not why people choose drama when we want to create robust application within the tools and
techniques to deal with uncertainties.
Inefficient, since all four tasks go into the same work as Red Deck, this team in various threads
will fight each other at the top of the deck over the four tasks.
This framework can never function efficiently in high performance environment, special purpose.
There are some restrictions to follow to make sure we can benefit from using.
For example, recommended restrictions must be plain.
That is mean between one hundred and ten thousand basic computational steps in the compute masset compute
intensive code only.
No blockin, no input.
Output, no synchronization, slow and unscalable, only works well on a small number of processors,
this design can never scale to hundreds or thousands of processors.
The overhead and reservation would nullify the benefits of additional processors exceedingly complex.
You can spend more time if you wish to investigate.
The source code of Thorbjoern framework was all Nasta types and how it is connected with the rest of
concurrent tools and JDK.
And you would agree that this is not the easiest and clear for understanding piece of JDK lacking in
professional attributes.
As a professional software engineer, as we always striving for excellence and following the best practices
some of them are, programs fail usually as a worst possible time.
Consequently, error recovery is paramount.
Software needs Deunan balancing of resources.
Administrators sometimes need classification, also called alerting logs and necessary.
The software should be useful across a wide range of computer needs.
The Fork Join Framework has none of this inadequate in scope.
The forging framework is only designed to work in a trivial segment of the computing world on Java standards
addition only on high performance workstations.
Six plus CPUs without high persuading do not compute, only work with no task input output, no Intertrust
concurrency and no networking.
So this is just some of the criticism against for of joint pool.
At the end of the day, it will be up to you how often and when to use it.
And now you have all necessary information to make this decision.
Let's recap what we have learned in this lesson.
In this lesson we learned what Fork Join framework is now, you know, the main masses of, for example,
class in the lesson.
We had some examples where the recursive action and recursive task, we executed these types of tasks
with the help of our gene pool.
And at the end of the lesson, we have discussed Fergin framework drawbacks.
That's it for this lesson.
Thanks a lot for your attention.
Have a great day and see you in the next lesson.