Can we increase the number of threads and cut down the process up to 1 second or 2 seconds? Is that Muti-Threading?
Let’s find the answer to this question through a small example.
Validate = 2s
Preparation = 3s
Currancy rate = 4s
Update model = 2s
Save = 4s
//So Can we use 5 threads and take this to 3 seconds?
No! That's not possible as there are dependency tasks here.✦ But we may do these tasks parallelly by using 2 different threads for first 2 steps.(Because all last 3 are dependency tasks) Then you could cut down the time little bit shorter than 15s.✦✦✦ So accordingly there's no way that you can increase the no of threads and cutdown the process upto 1s or 2s and That's not Multi Threading.
Multi-Threading can be defined as Multiple processes/Multi-tasking.
If you are using n number of files without any dependencies and you want to cut down its working time to a low time, and that cannot be done by exceeding the threads even more than n. (Of course, you could use n number of threads, but you can’t use more than n ) Because there is no point in using the same thread to do the same task.
How we can create a Thread?
◾️ By extending the Thread class
◾️ By implementing a runnable interface
What happens if a child class extends a thread class?
Let's understand this through a simple example
So if you want to convert this Runner into a thread, then you have to extend the Runner class from a thread class. So when it extends a thread class, the Runner-Sportsman relationship will break. (We can solve this issue by implementing the Runnable interface to create threads)
Some hidden scenarios associated with Threads
Is it a must to override the run() when extending the thread class?
Output - It will execute. But nothing will happen.
The procedure happens here:
✦ When goes to the start() method in the Application class; it will go to the Printer class and check the start() method.
✦ But as there is no start method in the Printer class, it goes to its parent class(Thread class) and checks the start() method.
✦ As there is a start() method in the Thread class, it will go inside this start()method in the Thread class.
✦Within the start(), they invoke a run().
✦ So again it comes to the Printer class and checks if there is any run() method. And as there's no run() method again it goes to the Thread class and checks any run() methods available there.
✦ And then it will execute the run() method in the Thread class.
But if you are implementing a Runnable interface, you must override all the methods in the interface including the run() method.
Each execution will have a different order, When executing the below program many times. Why?
When executing, there's no way to tell that the main or child thread will execute first as there is no such rule.
When starting a thread, it will add our thread to the thread scheduler. And how this Thread scheduler works fully depends on JRE( finally its JVM). And this order changes from JVM to JVM.
What’s the need for this start() method? So what will happen if we directly invoke the run method without calling the start method?
Let's understand the scenario using the following coding example:
OUTPUT - It will always execute the child class first before executing the main.
We don't have 2 threads according to this scenario.
Use of start() method:
✦✦✦✦ Before starting the thread, it does some tasks as below,
But if we call a start method, we do not need to do any of the above tasks and JVM will do that. So finally when invoking the start() method, JVM does essential things and invokes the run method.
What happens if we override a start method in the printer class(a class which extends the thread class)?
So here, the Printer class has a start method. So it will get executed when invoking the start method in the main class.
When overriding the start method, it will block creating a new thread. (Because it blocks to invoke the Thread class’s start method)
By using the Super. start(), we can override the start method and also will be able to create a thread.
What happens if we overload the run method?
Nothing will happen and it will create a thread. Because the start method will always invoke the run method with no arguments.
What happens when the main thread terminates? Will it affect the child thread?
No! Child thread can stay executing though the main thread terminates.
But if we want to make the child thread terminates after the main thread terminates, we have to set the child thread as a Daemon thread. (.setDaemon(true))
How to create Threads by implementing the Runnable interface ☛
The below code snippet shows the way to create the thread class by implementing the Runnable interface.
So as this class implementing the Runnable interface to give a thread behavior, this class doesn't have a start method to invoke. So we have to create an instance from the thread class and then have to pass the Runnable instance into that as follows.
Constructors of the Thread class
✦ Thread (Runnable target)
✦ Thread (Runnable target, String name)
✦ Thread (String name)
✦ Thread (ThreadGroup group, Runnable target)
✦ Thread (ThreadGroup group, Runnable target, String name)
✦ Thread (ThreadGroup group, Runnable target, String name, long stack size)
✦ Thread (ThreadGroup group, String name)
In java, thread priority ranges from 1–10. The maximum thread priority is 10, Lowest thread priority is 1.
The main thread’s default thread priority is 5. Thereafter any thread we create will inherit the parent thread’s value.
What happens if set the priority beyond the desired range?
It throws an illegal Argument Exception.
What happens if two threads carry the same priority?
Nothing much will happen. The thread scheduler will choose one thread to run.
Thread Life Cycle
Thread join method
The thread join method allows waiting until another thread finishes its execution.
Three different overloading functions in the join method are as follows
✯ .join(long milliseconds)
✯ .join(long milliseconds, int nanoseconds)
After any thread goes to its waiting state, there's no way to directly go to the running state. So it has to go again to the “Ready/Runnable” state.
Below are the cases that a thread that can go to the Runnable state.
✯✯✯ If any time out occurred.
✯✯✯ If the other thread completed its job.
✯✯✯ If someone interrupted the waiting state.
Thread yield() method
★ The yield method is a Native method.
★ Can be used in debugging scenarios. (When we want to give more chances to a particular scenario)
At the moment when a thread uses the yield method, that gives a signal to the Thread scheduler to give a chance to other thread. So if the thread scheduler decides to give the chance, then the particular thread who called the yield method will go to its “waiting state” and another thread will execute.
Thread sleep() method
★ Does not have a method without parameters.
★ Can wait for a certain given time.
★ Has two different method signatures.
- .sleep(long milliseconds) ⇾ This is a native method
- .sleep(long milliseconds, nanoseconds)⇾ This is not a native method
★ When calls a sleep(),
⇾ The thread goes to the waiting state for a particular give time frame. And it comes back if the waiting time is expired or if any interruption occurred.
Thread interrupt() method
★ One interrupt works only for one sleep moment.
★ If we call an interrupt method on a thread that is not sleeping ⇾ interrupt will wait until that thread goes to “sleep” or “waiting ” state and then will poke to that thread.
Java Concurrency - yield(), sleep() and join() methods - GeeksforGeeks
Java Concurrency - yield(), sleep() and join() methods We can prevent the execution of a thread by using one of the…