“Multithreading” is a great feature that enables the application to create small chunks of tasks and run them in parallel. The core difference between “Multitasking” and “Multithreading” is that in the former functionality, multiple processors share the resources i.e., the CPU. However, “Multithreading” extends the idea of “Multitasking” in applications where the target operations within an application can be subdivided into individual threads. It is such that multiple threads can run in parallel.
Contents Overview
- What is Java Multithreading?
- Thread Life Cycle
- Priorities of Threads
- How Does Java Support Multithreading?
- What is the Need For Multithreading?
- Advantages of Multithreading
- How to Create a Thread(s) in Java?
- What is the Difference Between the “Thread” Class and “Runnable” Interface?
- Java Thread Methods
- Static Thread Methods in Java
What is Java Multithreading?
“Multithreading” in Java is a functionality that enables concurrent execution of two or more code parts to use the maximum CPU. These parts in the code are referred to as “threads”.
Thread Life Cycle
In the above lifecycle:
- New: A new thread starts its life cycle in the new state.
- Runnable: After a new thread is started, the thread becomes runnable i.e., can run its task.
- Waiting: At times, a thread moves to this state while the thread waits for any other thread to do a task.
- Dead: A runnable/executable thread enters this state when it ends its task or else terminates.
Priorities of Threads
Each Java thread contains a priority based on which the OS analyzes the scheduling of threads.
These threads’ priorities are in the range of “MIN_PRIORITY (constant 1)” and “MAX_PRIORITY (constant 10)”. Each thread is assigned the priority “NORM_PRIORITY (constant 5)” by default.
It is such that the threads with higher priority are more vital to the code and need to be assigned the processor time before the lower-priority threads.
Note: Based on the thread priorities, the execution order of the threads cannot be guaranteed.
How Does Java Support Multithreading?
Java supports Multithreading with the help of the “Thread” class using which multiple threads can be created and started in the code. Java runtime helps in creating machine instructions and works with the OS to run them simultaneously.
What is the Need For Multithreading?
While executing a real-world application, the optimized processors are needed for fast execution but using only these fast processors cannot enhance the application’s speed. An effective approach to creating a performance-optimized application can be to make use of “Multithreading”.
Advantages of Multithreading
Following are some advantages of utilizing “Multithreading”:
- It doesn’t block the user since threads are independent.
- If an exception is faced in a particular thread, it doesn’t affect the other threads.
How to Create a Thread(s) in Java?
In Java, a thread(s) can be created via the following methods:
- Extending the Thread Class.
- Implementing the Runnable Interface.
What is the Difference Between the “Thread” Class and “Runnable” Interface?
The main differences between both approaches are as follows:
- Upon extending the “Thread” class, the class is not able to extend any other class as Java doesn’t support multiple inheritance. However, if the “Runnable” interface is implemented, the class is still able to extend to other base classes.
- Utilizing runnable gives an object that can be shared across multiple threads.
- The basic functionality of the thread can be achieved by extending the “Thread” class as it contains some methods such as interrupt(), yield(), etc that are unavailable in the “Runnable” interface.
Approach 1: Creating a Thread by Extending the “Thread” Class
In this approach, a class can be created/made that extends the “java.lang.Thread” class. This class overrides the “run()” method in the Thread class.
It is such that a thread starts its life within the “run()” method. Upon creating an object of the class(that extends the Thread class) and invoking the “start()” method, the execution of the thread starts by accessing the “run()” method on the Thread object:
package jbArticles;
class Multithread extends Thread {
public void run(){
try {
System.out.println( "Thread " + Thread.currentThread().getId()
+ " is running");
}
catch (Exception exc) {
System.out.println("Exception is Handled!");
}
}}
public class MultiThreading {
public static void main(String[] args) {
int num = 5;
for (int i = 0; i < num; i++) {
Multithread ob= new Multithread();
ob.start();
}
}}
In this snippet of code:
- Define a class named “Multithread” that extends the “Thread” class.
- In its definition, apply the “run()” method, and within the “try” block, use the “currentThread()” method to get a reference to the currently running thread object.
- This returns the thread that is running.
- Also, handle the faced exceptions, if any in the “catch” block.
- In “main”, specify the count of threads to execute.
- Lastly, apply the “for” loop and create a class object using the “new” keyword and the “Multithread()” constructor and invoke the “start()” method that starts the execution of threads.
Output
In this generated output, it is evident that the specified number of threads are running.
Bonus Tip: Java makes multiple Thread objects before the first one is created, therefore, the thread IDs “0-8” are already occupied and it is not guaranteed that this number will be sequential.
Approach 2: Creating a Thread by Implementing the “Runnable” Interface
In this method, a class is created that implements the “java.lang.Runnable” interface and overrides the “run()” method. After that, likewise, a Thread object is created and the “start()” method is invoked on this object:
package jbArticles;
class Multithread implements Runnable {
public void run(){
try {
System.out.println("Thread " + Thread.currentThread().getId()
+ " is running");
}
catch (Exception e) {
System.out.println("Exception is Handled!");
}
}}
public class MultiThreading {
public static void main(String[] args) {
int n = 7;
for (int i = 0; i < n; i++) {
Thread object= new Thread(new Multithread());
object.start();
}
}}
The code explanation is as follows:
- Declare a class named “Multithread” that implements the “Runnable” interface.
- In the class definition, likewise, apply the “run()” method to get the thread that is executing and handle the exceptions, if any, in the “catch” block.
- In “main”, specify the number of threads to execute.
- Finally, create a Thread object that takes the class object as the constructor’s argument and applies the “start()” method on the object to start the execution of threads.
Output
Here, it can be verified that the specified “7” threads are executed successfully.
Java Thread Methods
Method | Functionality |
---|---|
void start() | It starts the thread in a separate execution path. |
final void setPriority(int priority) | It sets the priority of the Thread object with values between “1” to “10”. |
final void join(long milliseconds) | The current thread accesses this method on the other thread, resulting in the blocking of the current thread till the other thread ends/terminates. |
final boolean isAlive() | It returns true if the thread is still alive i.e., any time after it is started. |
void run() | If the thread object is created via a separate Runnable, this method is accessed on that Runnable object. |
void interrupt() | It interrupts the thread, resulting in resuming execution if blocked for any reason. |
void setName(String name) | It changes/modifies the Thread object name and the name is returned via the “getName()” method. |
void setDaemon(boolean x) | The value “true” represents this thread as a daemon thread. |
Static Thread Methods in Java
Method | Functionality |
---|---|
void yield() | The current executing thread yields other threads having the same priority that are waiting to be scheduled. |
void dumpStack() | It shows the stack trace for the executing thread. |
void sleep(long milliseconds) | The currently running thread is blocked for the specified milliseconds. |
Thread currentThread() | It returns the reference to the currently executing thread. |
boolean holdsLock(Object x) | It gives true if the present thread has a lock on the provided object. |
Example: Applying the Thread Methods in Java
This code example applies the discussed thread methods in both the processes of creating a thread i.e., extending the “Thread” class and implementing the “Runnable” interface via individual classes:
package jbArticles;
class out implements Runnable {
private String mess;
public out(String mess) {
this.mess = mess;}
public void run() { while(true) {
System.out.println(mess);
}
}}
class Number extends Thread {
private int number;
public Number(int number) {
this.number = number;
}
public void run() {
int counter = 0;
int guess = 0;
do {
guess = (int) (Math.random() * 100 + 1);
System.out.println(this.getName() + " guesses " + guess);
counter++;
} while(guess != number);
System.out.println("** Correct!" + this.getName() + "in" + counter + "guesses.**");
}}
public class MultiThreading {
public static void main(String[] args) {
Runnable dis = new out("Hi");
Thread firstThread = new Thread(dis);
firstThread.setDaemon(true);
firstThread.setName("Hi");
System.out.println("Initiating Hi thread...");
firstThread.start();
Runnable bye = new out("Bye");
Thread secondThread = new Thread(bye);
secondThread.setPriority(Thread.MIN_PRIORITY);
secondThread.setDaemon(true);
System.out.println("Initiating Goodbye thread...");
secondThread.start();
System.out.println("Initiating thread 3...");
Thread thirdThread = new Number(5);
thirdThread.start();
try {
thirdThread.join();
} catch (InterruptedException e) {
System.out.println("Thread interrupted!");
}
System.out.println("Initiating thread 4...");
Thread thread4 = new Number(15);
thread4.start();
System.out.println("main() is ending...");
}}
In this block of code, consider the below-provided steps:
- First of all, define the class “out” that implements the “Runnable” interface.
- In its definition, create a parameterized class constructor that displays the passed message and likewise, access the “run()” method to get the thread being executed.
- Now, create a class “Number” that extends the “Thread” class.
- In its definition, similarly, create a parameterized class constructor that returns the passed value and the “run()” method that gives a calculated value via the “Math.random()” method and the Thread’s “getName()” method is applied to get the name.
- In the “main”, create an object of the former class(implementing the Runnable interface), pass the stated message as the constructor’s argument, and pass this object to the Thread’s object.
- Now, apply the Thread methods “setDaemon()” and “setName()” and “start() to represent a Daemon thread, set the name of the Thread object, and start the execution of the thread, respectively.
- Also, create another thread associated with the “out” class.
- Create an object of the class(the one extending the Thread class) and pass the given values i.e., “5” and “15” respectively.
- Repeat the process of starting the execution of the threads.
Output
This output implies that the threads associated with the individual classes are started appropriately.
Conclusion
“Multithreading” in Java enables the concurrent execution of two or more code parts to utilize the maximum CPU and multiple threads can be created by extending the “Thread” class or implementing the “Runnable” interface. Moreover, the thread methods can also be used to assign the thread as “daemon”, set the thread’s name, configure its priority, interrupt a thread, etc.