We may not have the course you’re looking for. If you enquire or give us a call on +91-181-5047001 and speak to our training experts, we may still be able to help with your training requirements.
Training Outcomes Within Your Budget!
We ensure quality, budget-alignment, and timely delivery by our expert instructors.
Do you ever find your Java programs running in a slow, linear fashion? Wouldn't it be amazing to leverage multiple processing lanes to get things done faster? Threads in Java are the secret weapon for achieving exactly that!
This comprehensive blog dives deep into the world of Threads in Java. We'll explore what threads are, how they work, and the advantages they offer for building efficient and responsive Java applications. Threads in Java empower your programs to handle multiple tasks concurrently, improving performance and user experience (UX). Feeling intrigued? Get ready to unlock the power of multitasking in Java and watch your programs take on a whole new level of efficiency!
Table of Contents
1) What is a Thread in Java?
2) Benefits of Using Threads in Java
3) Creating a Thread in Java
4) Java Thread Lifecycle
5) What is Main Thread?
6) Priorities of a Java Thread
7) Most Commonly Used Constructors in Thread Class
8) Commonly Used Methods of Thread class
9) Multithreading in Java
10) How to Handle Thread Deadlock
11) Java Process vs Java Thread – Key Differences
12) Conclusion
What is a Thread in Java?
A Thread can be defined as a lightweight sub-process which has its call stack and runs in parallel with other Threads. Thread in Java enables the efficient execution of multiple tasks simultaneously in a single program. Threads can be considered independent, concurrent execution paths within a program.
It can also be defined as the direction, which is taken, while a program is executed. In general, all the programs consist of at least one Thread which is also known as the main Thread. This is provided by Java Virtual Machine (JVM) at the beginning, when the program is being executed. At this starting point, when the main Thread is provided, the main () method is invoked, by this same main Thread.
Multitasking in Java is the process where you can perform multiple tasks at the same time. These tasks or processes can be divided into Threads which can be achieved through Multithreading. Let’s discuss the two ways in which multitasking in Java is performed:
a) Process-based multitasking: In this type of Multitasking the processes are heavy and a lot of time is consumed because the program takes a long time to switch between several different processes.
b) Multithreading: This involves the concurrent execution of two or more than two Threads which can be handled in the different parts of the program’s code. Multithreading in Java can be used efficiently for CPU resources, as Threads can run parallel to each other, especially on multi-core processors.
Benefits of using Threads in Java
There are many benefits to using Threads in Java, including the following:
a) Efficient Use of System Resources: Threads in Java can better use available system resources by allowing multiple tasks to run concurrently within a single program.
b) Improved Program Responsiveness: Multithreading can improve a program’ responsiveness, as it allows you to interact with the program while performing other tasks in the background.
c) Simplified Program Structure: By dividing a program into multiple Threads, it becomes easier to manage and maintain.
Understanding the Main Thread in Java
Java provides built-in support for multithreaded programming, allowing a program to contain multiple parts that can run concurrently. Each part is called a thread, and each thread defines a separate path of execution.
The Main Thread in Java
When a Java program starts, a thread begins running immediately. This is usually called the main thread because it is the thread that runs when the program begins.
Properties of the Main Thread
1) Parent Thread: The main thread is the thread from which other "child" threads are spawned.
2) Execution: Often, it must be the last thread to finish execution because it performs various shutdown actions.
Controlling the Main Thread
The main thread is created automatically when the program starts. To control it, we must obtain a reference to it. This can be done by calling the currentThread() method in the Thread class. This method returns a reference to the current thread. The default priority of the main thread is 5, and for all remaining user threads, priority will be inherited from parent to child.
Here is a Java program to demonstrate how to control the main thread:
// // Importing required classes import java.io.*; import java.util.*; // Main class extending Thread class public class Test extends Thread { // Main driver method public static void main(String[] args) { // Getting reference to Main thread Thread t = Thread.currentThread(); // Getting name of Main thread System.out.println("Current thread: " + t.getName()); // Changing the name of Main thread t.setName("Geeks"); System.out.println("After name change: " + t.getName()); // Getting priority of Main thread System.out.println("Main thread priority: " + t.getPriority()); // Setting priority of Main thread to MAX(10) t.setPriority(Thread.MAX_PRIORITY); // Print and display the main thread priority System.out.println("Main thread new priority: " + t.getPriority()); for (int i = 0; i < 5; i++) { System.out.println("Main thread"); } // Main thread creating a child thread Thread ct = new Thread() { // run() method of a thread public void run() { for (int i = 0; i < 5; i++) { System.out.println("Child thread"); } } }; // Getting priority of child thread which will be inherited from Main thread // as it is created by Main thread System.out.println("Child thread priority: " + ct.getPriority()); // Setting priority of child thread to MIN(1) ct.setPriority(Thread.MIN_PRIORITY); System.out.println("Child thread new priority: " + ct.getPriority()); // Starting child thread ct.start(); } } |
Output:
Current thread: main After name change: Geeks Main thread priority: 5 Main thread new priority: 10 Main thread Main thread Main thread Main thread Main thread Child thread priority: 10 Child thread new priority: 1 Child thread Child thread Child thread Child thread Child thread |
Creating a Thread in Java
There are two primary ways of creating a Thread in Java, which include the following:
1) Extension of the Thread class: You need to create a new class that extends the Thread class and override the run() method in order to create a new Thread. By extending the Thread class, you can create an instance of this class and start it using the start() method. Here's an example:
public class MyThread extends Thread { @Override public void run() { System.out.println("Starting MyThread"); for (int i = 0; i < 10; i++) { System.out.println(i); } System.out.println("Ending MyThread"); } } public class Main { public static void main(String[] args) { MyThread myThread = new MyThread(); myThread.start(); System.out.println("Finished"); } } |
Output:
Finished Starting MyThread 0 1 2 3 4 5 6 7 8 9 Ending MyThread |
This example creates a new Thread by overriding the run() method and extending the Thread class. The start() method is called to start the Thread, which executes the code in the run() method.
2) Implementing the runnable interface: To create a new Thread by implementing the runnable interface, you need to create a new class that implements the runnable interface and overrides the run() method. Then, you can create an instance of this class, wrap it in a Thread object, and start the Thread using the start() method. Here's an example:
public class MyRunnable implements Runnable { @Override public void run() { System.out.println("Starting MyRunnable"); for (int i = 0; i < 10; i++) { System.out.println(i); } System.out.println("Ending MyRunnable"); } } public class Main { public static void main(String[] args) { MyRunnable myRunnable = new MyRunnable(); Thread myThread = new Thread(myRunnable); myThread.start(); System.out.println("Finished"); } } |
Output:
Finished Starting MyRunnable 0 1 2 3 4 5 6 7 8 9 Ending MyRunnable |
This example creates a new Thread by overriding the run() method and implementing the runnable interface. An instance of this class is created and then wrapped in a Thread object. the start() method is called on the Thread object to start the Thread, which executes the code in the run() method.
Java Thread lifecycle
Java Threads have a defined life cycle consisting of five states: new, runnable, blocked, waiting, and terminated. The Thread goes through these states as it is created, started, and completes its execution. Here's a brief explanation of each state:
1) New State: It is in the new state when a new Thread object is created using the Thread class or by implementing the Runnable interface. At this point, the Thread has not yet started running.
2) Runnable State: When the start() method is called on a Thread object, the Thread moves to the runnable state. In the runnable state, the Thread is ready to be scheduled to run by the OS. However, it does not particularly mean that the Thread is currently executing or running.
3) Blocked State: A Thread may move to the blocked state if it needs to wait for a currently unavailable resource, such as input or output. The Thread is blocked until the resource becomes available.
4) Waiting State: A Thread may move to the waiting state if it is waiting for a notification from another Thread using the wait() method. The Thread will remain to wait until it receives a notification.
5) Terminated State: A Thread moves to the terminated state when it has completed its execution or has been stopped using the stop() method. Once a Thread is terminated, it cannot be restarted.
Baster the pillar of GUI programming with Java Swing Development Training - sign up soon!
Commonly Used Constructors in the Thread Class
The Thread class in Java includes various constructors and methods for creating and managing threads. The class extends Object and implements the Runnable interface. Below are the commonly used constructors in the Thread class:
Thread()
This is the default constructor, used to create a new instance of the Thread class.
Example:
Thread thread = new Thread(); |
Output:
Thread() |
Thread(String name)
This constructor creates a new Thread object and assigns a name to it.
Example:
Thread thread = new Thread("ThreadName"); |
Output:
Thread(String name) |
Thread(Runnable target)
This constructor accepts a Runnable object and creates a new Thread object.
Example:
Runnable runnable = new MyRunnable(); Thread thread = new Thread(runnable); |
Output:
Thread(Runnable target) |
Thread(Runnable target, String name)
This constructor creates a new Thread object by passing a Runnable reference as the first parameter and a name for the thread as the second parameter.
Example:
Runnable runnable = new MyRunnable(); Thread thread = new Thread(runnable, "ThreadName"); |
Output:
Thread(Runnable target, String name) class MyRunnable implements Runnable { public void run() { System.out.println("Thread is running"); } } public class MultithreadingExample { public static void main(String[] args) { Thread thread1 = new Thread(new MyRunnable()); thread1.start(); } } |
Thread is running |
Priorities of a Java Thread
Threads in Java have priorities that are used to determine their relative importance. The Thread priority range is from 1 (lowest) to 10 (highest). By default, all Threads are given a priority of 5.
The priority of a Thread determines how much CPU time it gets relative to other Threads in the system. Higher-priority Threads are more likely to get CPU time than lower-priority Threads, but there are no guarantees. It is also important to note that Thread priority is just a suggestion to the operating system (OS) and is not a hard and fast rule.
Here's an example to illustrate how Thread priorities work in Java:
public class PriorityExample implements Runnable { @Override public void run() { for (int i = 1; i <= 10; i++) { System.out.println(Thread.currentThread().getName() + " - " + i); } } public static void main(String[] args) { Thread t1 = new Thread(new PriorityExample(), "Thread 1"); Thread t2 = new Thread(new PriorityExample(), "Thread 2"); t1.setPriority(Thread.MAX_PRIORITY); // set t1 priority to maximum (10) t2.setPriority(Thread.MIN_PRIORITY); // set t2 priority to minimum (1) t1.start(); t2.start(); } } |
Start your coding journey with our JavaScript for Beginners Course now!
Commonly Used Methods of Thread class
The Thread class in Java facilitates multithreading, offering key methods like start() to begin thread execution, run() for defining thread tasks, and sleep() for pausing execution. join() waits for a thread to terminate. yield() suggests a pause to allow other threads to execute. interrupt() interrupts thread execution, handling exceptions. isAlive() checks if a thread is active. setName() and getName() manage thread identification. setPriority() and getPriority() set and retrieve thread priority levels. currentThread() identifies the currently executing thread. These methods enable efficient task distribution, resource sharing, and responsive applications in Java's concurrent programming environment.
Multithreading in Java
Multithreading in Java is the capability to run multiple threads simultaneously, maximising CPU utilisation. This technique, also known as concurrency, allows each thread to execute in parallel with others. Since threads share the same memory space, memory usage is more efficient, and context switching between threads is faster.
In Java, multithreading enhances the structure and readability of programs, making them easier to navigate and manage. It is particularly beneficial in high-server media applications, allowing for dynamic configuration changes and enhancements.
Example of Multithreading in Java
Here is a simple example of multithreading:
class MyRunnable implements Runnable { public void run() { System.out.println("Thread is running"); } } public class MultithreadingExample { public static void main(String[] args) { Thread thread1 = new Thread(new MyRunnable()); thread1.start(); } } |
Output:
Thread is running
How to Handle Thread Deadlock?
A deadlock occurs when multiple threads are indefinitely blocked, each waiting for a resource held by another thread. In Java, this often happens with synchronised blocks or methods where threads contend for locks in different orders.
To prevent deadlocks, ensure all threads acquire locks in a consistent order when accessing multiple resources. For instance, if one thread acquires lock A then lock B, other threads should follow the same sequence to avoid potential deadlocks.
For example, consider a scenario where Thread 1 holds lock A and waits for lock B, while Thread 2 holds lock B and waits for lock A. Both threads remain blocked, unable to proceed, resulting in a deadlock and halting further execution. Avoiding such situations requires careful design and consistent lock acquisition strategies across all threads involved.
Elevate your skills with our comprehensive Java Engineer Training today!
Java process vs Java Thread – Key differences
A question that often pops up for regular users of Java is how is a Java Process different from a Java Thread. Here is a table that summarises the differences between the both based on different criteria:
Basis of difference |
Java Process |
Java Thread |
Definition |
An instance of a Java Virtual Machine (JVM) running on a physical or a virtual machine. |
A lightweight unit of execution within a Java Process that shares memory and resources with other Threads within the same process. |
Resource allocation |
Each Java Process has a memory space of its own and set of system resources the operating system allocates. |
All Java Threads involved within a Process share its memory space and system resources. |
Communication |
Inter-process communication is required for communication between Processes. |
Inter-Thread communication can be done using mechanisms such as wait(), notify(), and notifyAll(). |
Context switching |
Context switching between processes is a heavyweight operation that involves saving and restoring the state of the entire process. |
Context switching between Threads is a lightweight operation that saves and restores only the Thread's state. |
Creation difficulties |
Creating a new Java Process has a relatively high cost regarding memory and system resources. |
Creating a new Java Thread has a relatively low-cost regarding memory and system resources. |
Concurrency |
Processes do not share memory or resources by default, so they must use inter-process communication mechanisms to coordinate their actions. |
Threads share memory and resources within the same process, making coordination and communication between threads easier. |
Scalability |
Creating multiple Java Processes can take up a lot of system resources and may not be scalable for large-scale applications. |
Creating multiple Java Threads within a Process is much more scalable and can be used to support high-concurrency applications. |
Error isolation |
Errors or crashes in one Process do not affect other processes running on the same system. |
Errors or exceptions in one Java Thread can potentially affect other Threads within the same Process. |
Security |
Running each process in its memory space can enhance security by isolating code and data. |
Threads are more susceptible to security threats, like malicious code, that can affect other Threads in the Process. |
Conclusion
In conclusion, Java Threads in Java are a powerful components of the Java programming language that allows for the concurrent execution of code. They provide a way to execute multiple tasks simultaneously, which can lead to significant performance improvements in applications that require parallel processing. They provide a powerful mechanism for executing multiple tasks concurrently within a single program. By dividing a program into multiple Threads, we can better use system resources, improve program responsiveness and simplify the automation of processes.
With this blog, we hope you understand Java Threads in detail, how to create and manage Threads, and the main points of distinction between Java Processes and Java Threads.
Build your aspiring Java career - Sign up for the course on Objected-Oriented Fundamentals Training in Virtual now!
Frequently Asked Questions
An example of Thread in Java is implementing runnable interface.
Threading in Java is a concept of concurrent execution of two or more than two parts of a program which maximises the utilisation of CPU resources. Each part of such a program is called a “Thread” and each Thread defines a separate path of execution.
The Knowledge Academy’s Knowledge Pass, a prepaid voucher, adds another layer of flexibility, allowing course bookings over a 12-month period. Join us on a journey where education knows no bounds.
The Knowledge Academy offers various Java courses, including Java Programming, JavaScript for beginners, and Java Swing Development Training. These courses cater to different skill levels, providing comprehensive insights into ArrayList in Java.
Our Programming & DevOps blogs covers a range of topics related to Java, offering valuable resources, best practices, and industry insights. Whether you are a beginner or looking to advance your Java programming skills, The Knowledge Academy's diverse courses and informative blogs have you covered.
The Knowledge Academy takes global learning to new heights, offering over 30,000 online courses across 490+ locations in 220 countries. This expansive reach ensures accessibility and convenience for learners worldwide.
Alongside our diverse Online Course Catalogue, encompassing 17 major categories, we go the extra mile by providing a plethora of free educational Online Resources like News updates, Blogs, videos, webinars, and interview questions. Tailoring learning experiences further, professionals can maximise value with customisable Course Bundles of TKA.