The goal of concurrency is to help your application perform better.
Concurrency means making progress on more than one task at a time.
And we can use multithreading to achieve concurrency.
In this lesson, you're going to learn about concurrency and multithreading.
First, open up the folder for this lesson by following this path in your course of resources.
Serial execution means running tasks one at a time, one after another.
This, as an example of serial execution tasks are being performed one by one.
The problem with serial execution is that when you have heavy tasks, they're going to block the main
thread for a long time before it can go to the next task.
If we go to a single thread, dot Java and run the code Opper to break points first and foremost.
We can see that this task, if we step over it, it's going to block the main thread for three whole
seconds.
Only then we can perform the other tasks.
This is really, really bad.
Long running tasks should not block the main thread, long running tasks should you run on another thread.
And that is when you would need to use concurrent execution.
Concurrent execution means making progress on more than one task at a time.
We can achieve concurrency with multi-threading.
An example would be one thread performing one set of tasks, while another thread performs another set
of tasks at random, a scheduler is going to say, OK, I'll run some parts of this task.
OK, now I'll switch over to another thread to run some of its tasks, and then we'll switch back to
that thread.
And it's totally random.
It's extremely hard to predict in what order it's going to accomplish our tasks.
But the take home message is that we can use concurrency to make progress on more than one task at a
time.
And in order to achieve concurrency, you need to learn how to create threads.
Well, we're going to do is run code that isn't time intensive on the main thread.
Run code that is time intensive on another thread.
In Java, you can create a thread object as follows create a new thread objects and give the thread
a runnable task.
So inside multithreaded Java.
Oh, create a new object of the thread class thread thread two is equal to a new thread.
That invokes a runnable task.
Now we have to define a reasonable task, and the way to do that is to create an object of a class that
implements the runnable interface.
The runnable interface forces our class to override the run method.
And here is where you would call the long running task.
So back here in our code, we can create a class static class long task.
That implements the runnable interface.
And here you can see we're being forced to override the run method.
So we'll do just that.
An inside run is where you would call the long running task.
OK, now inside the main method, we're going to create a new object of the long task class, long task,
we'll call it runnable.
The runnable task is an equally new instance of long task.
And we're good.
We're going to be executing this runnable task on threat, too.
And finally, in order to run this thread, we're just going to call threat to Dutch starts.
So we can expect that this long task isn't going to block the main threat anymore.
Let's run the app.
And beautiful.
This long task is running in the background, and it doesn't block the main threat anymore.
We're making progress on more than one task at a time.
Now, is there a better way to create a runnable that was really messy?
And yes, there is.
We can use an anonymous class.
If you look at this class, it's just a placeholder.
It doesn't have any fields, it doesn't have any special methods, its only purpose.
It's only there so that we can create an object of a class that is of type runnable.
What if I told you we can just remove the class altogether?
And if we just have the interface of Runnable.
Obviously, we can't create a runnable object, we'd get an error.
It's just an interface.
But if we add two brackets.
This syntax means, OK, we're creating an object of an anonymous class that implements the runnable
interface and this anonymous class, it doesn't have a name, but it has to override the method of the
interface it implements.
In this case, this anonymous class has to override the run method.
Here is where you would invoke your long task.
We were on the up and everything works beautifully.
But I don't know about you, this is also a pretty ugly.
Here's a rule of thumb for you.
If the interface only holds one method, we can replace an anonymous class with a lambda expression.
Here is where you would put in your task and magically what you put here is going to stand in for the
run method.
And so now, when our thread calls Runnable Run behind the scenes, it's not passing in any arguments.
So it follows that the lambda expression receives no parameters.
And the arrow key points to a block of code that's going to get executed in this case, what gets executed
is our long running task.
And this, to me, looks a lot better.
So back here, we can delete this monstrosity and when possible, I try to avoid creating anonymous
classes and just use a lambda expression.
Thank goodness for Java eight and lambda expressions.
They really were a milestone in programming, rewriting our code.
Everything works really well.
Concurrency makes progress on more than one task at a time.
Time intensive tasks should never blocked the main thread.
Time intensive tasks should run on a separate thread as our normal code ran on the main thread.
We executed the long running code, any background thread.