In this tutorial series, we are learning multithreading in Java. This is the first article in the series. Here we are going through the basic concept of multithreading.
Multitasking
Executing several tasks simultaneously is the concept of multitasking
There are two types of multitasking:
Process-based Multitasking
Thread based Multitasking
Process-based Multitasking
Executing several tasks simultaneously where each task is a separate independent program(process) is called process-based multitasking.
For e.g. While typing java code, you can listen to songs, at the same time you can download your favorite movie. So all these tasks are executing simultaneously and independently of each other.
It is best suitable at the Operating System level.
Thread based Multitasking
Executing several tasks simultaneously where each task is a separate path of the same program. Each independent path is nothing but the thread.
It is best suitable at the Programming level.
The objective of multithreading is to reduce the idle time of the processor and improve the performance of the system
Application of Multithreading:
To develop multimedia graphics
To develop Animation
To develop Video games
To develop Application server and Webserver
Developing multithreading application in java is very easy because Java provides inbuilt support for multithreading with rich API
The way of defining a thread
We can define a thread in the following two ways:
By extending Thread class
By implementing Runnable Interface
1) By extending Thread class
class MyThread extends Thread{ public void run(){ for (int i = 0; i < 5; i++) { System.out.println("Child thread : "+i); } } } public class Test1 { public static void main(String[] args) { MyThread mt = new MyThread(); mt.start(); for (int i = 0; i < 5; i++) { System.out.println("Parent thread : "+i); } } }
o/p:- Main Thread - 0 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
2) By implementing Runnable Interface
Runnable Interface present in java.lang package and contains only one method i.e. public void run()
class MyRunnable implements Runnable { public void run() { for (int i = 0; i < 5; i++) { System.out.println("Child thread : " + i); } } } public class Test1 { public static void main(String[] args) { MyRunnable mr = new MyRunnable(); Thread mt = new Thread(mr); mt.start(); for (int i = 0; i < 5; i++) { System.out.println("Parent thread : " + i); } } }
Parent thread : 0 Parent thread : 1 Parent thread : 2 Child thread : 0 Child thread : 1 Child thread : 2 Child thread : 3 Parent thread : 3 Child thread : 4 Parent thread : 4
Thread Scheduler
It is part of JVM responsible to schedule threads i.e if multiple threads are waiting for execution then which thread execute next is decided by the thread scheduler. We can't expect an exact algorithm followed by thread schedular. It is varied from JVM to JVM. Hence we can't predict order and exact output.
Difference between t.start() and t.run()
When t.start() called new thread will be created, which is responsible for the execution of the run() method.
When t.run() called new thread won't be created, and run() method will be executed just like a normal method called by the main thread.
In above program if we replace mt.start() with mt.run() then o/p will be:Child thread : 0 Child thread : 1 Child thread : 2 Child thread : 3 Child thread : 4 Parent thread : 0 Parent thread : 1 Parent thread : 2 Parent thread : 3 Parent thread : 4
Importance of thread class start() method
The Thread class start() method is responsible for registering the thread with the thread schedular and all other registration activities. Hence without executing the start() method there is no chance of starting a new thread in java.
t.start(){ 1) Registring this thread in thread schedular. 2) Perform all mandatory activities. 3) Call run() method. }
Overload run() method
We can overload run() method, but Thread classes start() method can invoke only no-args run() method. The other overloaded methods we have to call explicitly like normal methods.
class MyRunnable implements Runnable { public void run() { for (int i = 0; i < 5; i++) { System.out.println("Child thread : " + i); } } public void run(int i){ for (int j = 0; j < i; j++) { System.out.println("run method call : "+ j); } } } public class Test1 { public static void main(String[] args) { MyRunnable mr = new MyRunnable(); Thread mt = new Thread(mr); mt.start(); mr.run(2); for (int i = 0; i < 5; i++) { System.out.println("Parent thread : " + i); } } }
O/P: run method call : 0 Child thread : 0 run method call : 1 Child thread : 1 Parent thread : 0 Child thread : 2 Parent thread : 1 Child thread : 3 Child thread : 4 Parent thread : 2 Parent thread : 3 Parent thread : 4
If we are not overriding run() method the Thread class run() method will be executed which has empty implementation and we can't get any output. Hence it is highly recommended to override run() method otherwise don't go for the multithreading concept.
class MyThread extends Thread { } public class Test1 { public static void main(String[] args) { MyThread mt = new MyThread(); mt.start(); } } O/P - // No output
Overriding start() method
If we override the start method then our start() method will be executed just like a normal method call and a new thread won't be created.
class MyThread extends Thread { public void start(){ System.out.println("Override start()"); } public void run(){ System.out.println("Child method."); } } public class Test1 { public static void main(String[] args) { MyThread mt = new MyThread(); mt.start(); System.out.println("Main method"); } }
Override start() Main method
It is not recommended to override start() method, otherwise don't go for multithreading.
Note:- After starting a thread if we are trying to restart the same thread then we will get runtime exception Illegalthreadstateexception.
Exampleclass MyThread extends Thread { public void run(){ System.out.println("Child method."); } } public class Test1 { public static void main(String[] args) { MyThread mt = new MyThread(); mt.start(); mt.start(); } }
Let's see what will happen in the following cases:
MyRunnable r = new MyRunnable(); Thread t1 = new Thread(); Thread t2 = new Thread(r)
t1.start()
A new thread will be created which is responsible for the execution of the Thread class run() method, which has an empty implementation.
t1.run()
No new thread will be created. Thread class run() method will be executed just like a normal method
t2.start()
A new thread will be created which is responsible for the execution of MyRnnable run() method will be executed just like normal method
t2.run()
New thread will not be created and MyRunnable run() method will be executed just like normal method
r.start()
Get compile-time error saying that MyRunnable class doesn't have the capability to start a thread
r.run()
No new thread will be created and MyRunnable run() method will be executed just like a normal method call
Which approach is best to define thread?
Among 2 ways of defining thread, implements a runnable approach is recommended to use. Because in the 1st approach our class extends thread class, there is no chance of extending any other class hence we are missing inheritance benefits here. But in the second approach while implementing the Runnable interface we can extend any other class.
Summary of thread constructors
Thread t = new Thread()
Thread t = new Thread(Runnable r)
Thread t = new Thread(String name)
Thread t = new Thread(Runnable r, String name)
Thread t = new Thread(ThreadGroup g, String name)
Thread t = new Thread(ThreadGroup g, Runnable r)
Thread t = new Thread(ThreadGroup g, Runnable r, String name)
Getting and Setting name to the thread
Every thread in java has some name, it may be the default name generated by JVM or a customized name provided by the programmer.
Methods :
getName() - To get thread name
setName() - To set thread name
Thread Priorities
- Priorities is always in range of 1 to 10
- Min Priority = 1
- Max Priority = 10
Every thread in Java has some priority. It may be default priority generated by JVM or priority is given by the programmer.
Default Priorities by Thread class :
Thread.MIN_PRIORITY = 1
Thread.MAX_PRIORITY = 10
Thread.NORM_PRIORITY = 5
Thread schedular will use priorities while allocating processor. Thread having the highest priority will get the chance first.
If 2 threads having the same priority then we can't expect the exact execution order. It depends on the thread schedular.
Example of getting and setting the priority of thread:
package mt; public class ThreadPriorityExample { public static void main(String[] args) { Thread t = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + " : " + i); } } }); System.out.println("Main class thread name : " + Thread.currentThread().getName()); System.out.println("Newly created thread name : " + t.getName()); t.setName("Local worker thread"); System.out.println("Name assigned to new thread using - t.setName() : " + t.getName()); t.setPriority(2); Thread.currentThread().setPriority(10); System.out.println("Main class thread priority : " + Thread.currentThread().getPriority()); System.out.println("Assigned highest priority to new thread using - t.setPriority() : " + t.getPriority()); t.start(); for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + " : " + i); } } } /* Output - Main class thread name : main Newly created thread name : Thread-0 Name assigned to new thread using - t.setName() : Local worker thread Main class thread priority : 10 Assigned highest priority to new thread using - t.setPriority() : 2 main : 0 main : 1 main : 2 main : 3 main : 4 Local worker thread : 0 Local worker thread : 1 Local worker thread : 2 Local worker thread : 3 Local worker thread : 4 */
Note: The default priority of the main thread is 5. For all remaining thread except the main thread, the default priority is inherited from its parent thread.
Summary of this post:
What we learned?
What is multitasking?
Difference between process-based and thread-based multitasking
Way of defining threads
What is thread schedular
Differenc between t.start() and t.run()
Importance of start() method
Impact of overloading run() method
Overriding start() method
Overriding start() method
With this, we also came to the end of this article. Please let us know your views and opinions in the comment section below. I hope you enjoyed this post. Please stay with us for more posts.
For more details on multithreading please refer Video
0 comments:
Post a Comment