What is multithreading?
Multithreading is a type of multitasking in the programming language where multiple tasks are executed simultaneously.
We have two different types of Multitasking
- Process-based Multitasking also called Multiprocessing is performed at the Operating System level. In this case, each task is a separate independent process. Example: While typing a java program in an editor we can also listen to audio songs from the same system at the same time, and we can also download the file at the same time. Different address spaces are shared to perform each task.
- Thread-based multitasking also called Multithreading is performed at the programming level. In this case, each task is a separate independent part of the same program. That each independent part is called a Thread. The same address space is shared for this case. The objective of multithreading is to reduce the response time of the system and improve its performance.
What is Thread?
A thread is a flow of execution in the java program with an independent path within the program.
How to create a Thread in Java?
We can define a thread in two different ways
- By Extending a Thread class.
- By implementing a Runnable interface.
By extending a Thread class:
As shown in the below program we have created the Thread named MyThread which is extending the Thread class. We need to override the run method in the child class MyThread.
To run the thread need to use start method of the Thread class. Main Thread and Child Thread will run in parallel hence we can not pretend the output of the program.
public static void main(String args[]) {
MyThread myThread = new MyThread();
myThread.start();
for (int i = 0; i < 5; i++) {
System.out.println(“Main Thread: ” + i);
}
}
}
class MyThread extends Thread {
// overriding the run method of thread class
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(“Child Thread: ” + i);
}
}
}
Main Thread: 1
Child Thread: 0
Child Thread: 1
Main Thread: 2
Main Thread: 3
Main Thread: 4
Child Thread: 2
Child Thread: 3
Child Thread: 4
By implementing a Runnable interface:
As shown in the following program we are implementing from the Runnable interface instead of extending from the Thread class. Note that we are overriding the run method from the Runnable interface in our child Thread class. To start the thread we need to assign our MyThread object as a thread by using the Thread class constructor and then start the child thread. Main Thread and Child Thread will run in parallel hence we can not pretend the output of the program.
public static void main(String args[]) {
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();
for (int i = 0; i < 5; i++) {
System.out.println(“Main Thread: ” + i);
}
}
}
class MyThread implements Runnable {
// overriding the run method of Runnable interface
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(“Child Thread: ” + i);
}
}
}
Main Thread: 1
Child Thread: 0
Main Thread: 2
Child Thread: 1
Main Thread: 3
Child Thread: 2
Main Thread: 4
Child Thread: 3
Child Thread: 4
Note That:
- Main Thread is always present in our java code which is responsible to call the main method. That is public static void main(String[] args) method is called by the main thread when we run the Test class.
- When we run the Test class at that time one thread is already present in our program, and when a start() method is called by the main thread inside the main method, a child thread is also gets created, which means we have two threads running after calling start() method.
What is Thread Scheduler?
This is a part of JVM which is responsible to schedule the Threads that is if multiple threads are present in the program and waiting to get the chance of the execution then in which order threads will be executed will be decided by Thread Scheduler. The algorithm followed by the Thread Scheduler is varied from JVM to JVM.
Hence we can not expect the exact order of Thread’s execution of exact output.
Difference between start() and run() method:
- start() method creates the new thread and is responsible for the execution of the run() method.
- the run() method will not create a new thread. If we directly call the run() method instead of the start() method though we will get the same output in the case of the above 2 programs no new thread will be created. This run method will be executed as a normal method call.
Importance of the start() method from Thread class:
- This is responsible to register the thread with the thread schedular and all other mandatory activities.
- Hence if we did not call the start method no thread will be created, hence start() method is considered the heart of the multithreading.
Overloading of run() method:
- Overriding the run() method is always possible, but the thread class start() method will always invoke the no-arg run() method.
- To call other overloaded run methods, we need to call them explicitly like a normal method call.
What if we did not override the run() method?
If we do not override the run method, then the Thread class run method will be executed. Note that it’s highly recommended to override the run method in the child thread.
What if we override the start() method?
- If we override the start() method in our child thread class, childThread.start() method call will be executed as a normal method call, no new thread will be created, and the run() method will not be executed automatically.
- If we add super.start() in our overridden start() method then a new thread will be created and the run method will be executed automatically.