Back to: Java Tutorials For Beginners and Professionals
Multithreading in Java with Examples
In this article, I am going to discuss Multithreading in Java with examples. Multithreading is one of the most important concepts in Java that you need to understand as a developer to achieve better performance. As part of this article, I am going to cover the following pointers which are related to Java Multithreading.
- What is Single-Tasking?
- What is Multitasking?
- How the operating system executes multiple applications at a time?
- Types of Multi-Tasking
- Processor-based multitasking (Multiprocessing)
- Thread-based multitasking (Multithreading)
- Advantages of Multitasking
- How can we create multiple threads in Java Program?
- What are Java Threads?
- What are Sequential execution and concurrent execution?
- What is Thread?
- Advantages of a single-threaded application
- What is Multithreading in Java?
- Advantages of Java Multithreading
- Why do we need multithreading in Java?
- How can we create user-defined threads in Java?
- What are the Different Ways to Create Custom Threads in Java?
- Processes and Threads in Java
- Difference Between Process and Thread
- What is Main Thread and the Main Thread so important?
What is Single-Tasking?
Single-Tasking means executing one task at a time. Here much of the processor time will be wasted because waiting time is very high and the processor gives a late response. Example: DOS
What is Multitasking?
Windows operating system is a multitasking operating system. It means it has the ability to run multiple applications at the same time. For example, in my machine, I can open the Google Chrome Browser, Microsoft word document, Notepad, VLC Media Player, Windows Explorer, etc. at the same time. This is possible because on my machine I have installed the Windows operating system and the Windows operating system is a multitasking operating system.
How the operating system executes multiple applications at a time?
To execute all the above applications, the operating system internally makes use of processes. A process is a part of the operating system (or a component under the operating system) which is responsible for executing the program or application. So, to execute each and every program or application, there will be a process.
You can see this using the Task Manager. Just right-click on the Taskbar and click on the Task Manager option which will open the Task Manager window. From that window, just click on the “Processes” button as shown below.
As you can see from the above image, each application is executed by one corresponding process. Along the same line, there are also multiple processes that are running in the background which are known as the background processes. These background processes are known as windows services and the Operating system runs a lot of windows services in the background.
So, we have an operating system and under the operating system, we have processes that run our applications. So under the process, an application runs. To run the code of an application the process will make use of a concept called Thread.
Types of Multi-Tasking
We can achieve multitasking in the following two ways:
- Processor-based multitasking (Multiprocessing)
- Thread-based multitasking (Multithreading)
Processor-based multitasking (Multiprocessing)
Processor-based multitasking means executing multiple tasks at the same time simultaneously where each task is independent of other tasks having separate memory and resources. Processor-based multitasking is an operating system approach.
For example, while typing a java program we can listen to a song and at the same time we can download a file from the internet, all these tasks are executed simultaneously and there is no relationship between these tasks. All these tasks have their own independent address space as shown below. This type of multi-tasking is developed at the OS level.
Thread-based multitasking (Multithreading)
Thread-based multitasking means executing different parts of the same program at the same time simultaneously where each task is independent sometimes or dependent sometimes on other tasks which are having common memory and resources.
Executing multiple tasks concurrently is called thread-based multitasking. Here each task is a separate independent part of a single process. That part is called a thread. This type of multitasking is developed at the programmatic level. Example: Games, Web-based applications, etc. For better understanding, please have a look at the below diagram.
Understanding some terminology:
Time Slice / Time Quantum:
For executing each task a unit of CPU time is given for its execution which is called a time slice or time quantum. The thread scheduler runs each thread for a short amount of time. Each thread alternatively gets a slice (quantum) of the CPU’s time.
Thread Scheduler :
Thread Scheduler is the Operating System program that is responsible for allocating the resources for threads and executing them. Thread Scheduler in java is the part of the JVM that decides which thread should run. There is no guarantee that which runnable thread will be chosen to run by the thread scheduler. Only one thread at a time can run in a single process. The thread scheduler mainly uses preemptive or time-slicing scheduling to schedule the threads.
Context Switching :
Context Switching is the process of loading or unloading the processes or tasks into or from the CPU. It means switching the CPU to another process requires saving the state of the old process and loading the saved state for the new process. This is done in assembly language. It works at the level of the procedure calling convention, so it cannot be implemented using procedure calls.
Advantages of Multitasking:
Whether it is a process-based or thread-based multitasking the advantage of multitasking is to improve the performance of the system by decreasing the response time.
Note: In general process-based multitasking is called just multitasking and thread-based multitasking is called multithreading.
The Difference between Multitasking and Multithreading is:
Multitasking is heavyweight because switching between contexts is slow as each process is stored at a separate address as we already discussed. Multi-threading is lightweight because switching between contexts is fast as each thread is stored in the same address as we already discussed.
How can we create multiple threads in Java Program?
We can develop a multithread program in java very easily because java provides in-build support for creating custom threads by providing API- Runnable, Thread, ThreadGroup.
What are Java Threads?
We can consider JVM is also a process, when JVM is created in its java stack area by default two threads are created with names
- Main- to execute the java methods
- Garbage collector- to destroy unreferenced objects
So by default java is a multithreaded programming language. All methods are executed in the main thread in sequence in the order they are called from the main. So by using a single thread JVM executes methods sequentially one after one.
What are Sequential execution and concurrent execution?
Sequential execution means single-thread execution and it takes more time to complete all methods of execution. Whereas concurrent execution means multithreading execution and it takes less time to complete all methods of execution. To have concurrent execution developers must create user-defined threads in the program.
Meaning of concurrent execution?
Executing multiple tasks in the “start-suspend-resume-end” fashion is called concurrent execution. This means both tasks are started at different points in time and one task is paused while another task is executed. In java, the JVM allows an application to have multiple threads of execution running concurrently. When a program contains multiple threads then the CPU can switch between the two threads to execute them at the same time. The important point to be remembered at a single instance time JVM cannot execute two tasks at a time.
What is Thread?
Generally, a Thread is a lightweight process. In simple words, we can say that a Thread is a unit of a process that is responsible for executing the application code. So, every program or application has some logic or code, and to execute that logic or code, Thread comes into the picture.
By default, every process has at least one thread that is responsible for executing the application code and that thread is called Main Thread. So, every application by default is a single-threaded application.
A thread is a:
- Facility to allow multiple activities within a single process
- A thread is an independent sequential flow of execution/path.
- A thread is a stack created in the java stack area.
- Referred to as a lightweight process
- A thread is a series of executed statements.
- Each thread has its own program counter, stack, and local variables
- It executes methods in sequence one after one.
- A thread is a nested sequence of method calls
- Its shares memory, files, and per-process state
- Java uses threads by using a “Thread Class”.
Advantages of a single thread:
- Reduces overhead in the application as a single thread execute in the system
- Also, it reduces the maintenance cost of the application.
Single Thread Example:
public class SingleThread { public static void main(String[] args) { System.out.println("Single Thread"); } }
Output: Single Thread
What is Multithreading in Java?
It is a process of creating multiple threads in the Java Stack Area (JSA) for executing multiple tasks concurrently to finish their execution in a short time by using the processor’s ideal time effectively.
Multithreading means executing multiple threads at the same time simultaneously where each thread is called a separated task of the program that executes separately.
Java is a multi-threaded programming language which means we can develop a multi-threaded program using Java. A multi-threaded program contains two or more parts that can run concurrently and each part can handle a different task at the same time making optimal use of the available resources especially when your computer has multiple CPUs. Hence, it is also known as Concurrency in Java.
Advantages of Java Multithreading:
- The users are not blocked because threads are independent, and we can perform multiple operations at times
- As such the threads are independent, the other threads won’t get affected if one thread meets an exception.
Why do we need multithreading in Java?
We need multithreading mainly for two reasons.
- To complete the execution of independent multiple tasks in a short time
- To effectively utilize the CPU’s ideal time.
What are the Different Ways to Create Custom Threads in Java?
In java, we can create user-defined threads in two ways
- Implementing Runnable interface
- Extending Thread Class
In both approaches we should override the run() method in a subclass with the logic that should be executed in the user-defined thread concurrently and should call the start() method on the Thread class object to create a thread in the java stack area.
Creating Thread by extending Thread class
If we want to create the threads using this approach, we have to follow the following five steps:
Step-1: Creating a class that extends a Thread class
class Mythread extends thread{
}
Step-2 : Overriding the run() method
public void run(){
//statements;
}
Here, the run() method is called the entry-point for the user-defined thread, and all the jobs are done by the user-defined thread will be written here itself.
Step-3: Creating an object for user-defined Thread class
MyThread t1 = new MyThread();
Step-4: Attaching user-defined Thread with main ThreadGroup
Thread t = new Thread(mt);
Step-5: Starting the execution of the Thread by calling start()
t.start();
When we call the start() method the thread will be registered with ThreadScheduler and next will invoke the run() method.
Creating Thread by implementing Runnable Interface
If we want to create the Thread using this approach we have to follow the following five steps:
Step-1: Creating a class that implements the Runnable interface
class MyThread implements Runnable{
}
Step-2 : Overriding the run() method
public void run(){
//statements;
}
Step-3: Creating an object for user-defined Thread class
MyThread the = new MyThread();
Step-4: Attaching user-defined Thread with main ThreadGroup
Thread t = new Thread(mt);
Step-5: Starting user-defined Thread by calling the start() method
t.start();
Lets us create the thread in two ways
In the first approach when we create a subclass object, the Thread class object is also created by using its no-argument constructor. Then when the start method is calling using a subclass object custom thread is created in the java stack area and its execution is started by executing the run() method from the subclass based on processor busy.
In the second approach when we create a subclass object, the Thread class object is not created because it is not a subclass of Thread. So to call the start method we should create a Thread class object explicitly by using the Runnable parameter constructor, then using this Thread class object we should call the start method. The custom thread is created in the java stack area and its execution is started by executing the run method from the Runnable interface subclass based on processor busy.
Example to create the Thread by extending the Thread class in Java
class MyThread12 extends Thread { public void run () { for (int i = 1; i <= 10; i++) { System.out.println ("User Thread Value:" + i); } } } public class MyThread2 { public static void main (String[]args) { MyThread12 mt = new MyThread12 (); Thread t = new Thread (mt); t.start (); } }
Output:
Example to create a thread by implementing the Runnable Interface in Java
class MyThread123 implements Runnable { public void run () { for (int i = 1; i <= 10; i++) { System.out.println ("User Thread Value:" + i); } } } public class MyThread3 { public static void main (String[]args) { MyThread123 mt = new MyThread123 (); Thread t = new Thread (mt); t.start (); } }
Output:
Difference between extending thread class and implementing a runnable interface
If we create any thread by extending the Thread class then we have no chance of extending from any other class. But if we create any thread by implementing the Runnable interface then we have a chance for extending from one class. It is always recommended to create the user define threads by implementing Runnable Interface only.
Can we call run() method directly? OR What is the difference between calling t.run() and t.start()?
Yes, we can call the run() method directly. In this, the code is valid but no thread will be created/registered with Thread Scheduler but the run() method executes like a normal method by Main Thread. But if we call the start() method thread will be registered with ThreadScheduler and calls run().
Example:
class MyThread11 implements Runnable { public void run () { Thread t = Thread.currentThread (); for (int i = 1; i <= 10; i++) { System.out.println (t.getName () + "value:" + i); } } } public class Thread2 { public static void main (String[]args) { MyThread11 mt = new MyThread11 (); Thread t = new Thread (mt); // t.run(); t.start (); } }
Output:
In the above program if we call t.start() then the thread will be created and the output will be displayed like follows:
Can we start a thread twice in Java?
No. After starting a thread, it can never be started again. If you do so, an IllegalThreadStateException is thrown. In such a case, the thread will run once but for the second time, it will throw an exception.
Processes and Threads in Java
Single Application running in OS is a process. A process can have multiple threads. For Example, Spell-checker in Microsoft word application can be considered a Thread, and a Microsoft word application is a process. Microsoft word application, is a single process and when you type in the word, a spell checker will keep working in the background to correct your words, this job can be considered as a thread.
Java application running in a system is a process and can have multiple threads inside it. A thread is nothing but a thread of execution that executes the code.
When you use the java class – your main method starts getting executed – It means that the JVM is creating a thread to start executing the code in the main method and we call this thread as Main Thread.
It is the Operating System that schedules the threads to be processed by the Processor. So the scheduling behavior is dependent on the OS. Again there is a Thread Scheduler inside JVM which coordinates with OS Scheduler.
Difference Between Process and Thread
Process:
- The process is heavyweight or resource-intensive.
- Process switching needs interaction with the operating system.
- In multiple processing environments, each process executes the same code but has its own memory and file resources.
- If one process is blocked then no other process can execute until the first process is unblocked.
- Multiple processes without using threads use more resources.
- In multiple processes, each process operates independently of the others.
Thread:
- Thread is lightweight taking lesser resources than a process.
- Thread switching does not need to interact with the operating system.
- All threads can share the same set of open files and child processes.
- While one thread is blocked and waiting, the second thread in the same task can run.
- Multiple threaded processes use fewer resources.
- One thread can read, write, or change another thread’s data.
What is the Main Thread in Java?
For every Java program, there will be a default thread created by JVM which is nothing but Main Thread. The entry point for Main Thread is the main() method.
Why is Main Thread so important?
- Because this thread affects the other ‘child’ threads
- Because it performs various shutdown actions
- It is created automatically when your program is started.
Example to display the info of the currently Running Thread in Java
public class ThreadingDemo { public static void main (String[]args) { Thread ct = Thread.currentThread (); System.out.println (ct); System.out.println (ct.getName ()); System.out.println (ct.getPriority ()); System.out.println (ct.getThreadGroup ()); } }
Output:
Here, Thread.currentThread() method gives the information of the currently running thread like Thread name, Thread priority, and ThreadGroup name to which it belongs.
In the next article, I am going to discuss the Java Thread Class in detail i.e. the methods and constructors of the thread class in Java with examples. Here, in this article, I try to explain Multithreading in Java with Examples. I hope you enjoy this Multithreading in Java with Examples article.