Do you think IIT Guwahati certified course can help you in your career?
No
Introduction
Hello, ninjas.Do you know what a thread is? Have you ever heard something about the Runnable interface in Java? If not, then don't worry. Coding Ninjas got your back. We will clear all your doubts.
In this article, we will discuss the Runnable interface in Java. We will cover how we can create a thread using the Runnable interface. We will also understand how the Runnable interface works. Before diving deeper into the topic, let us understand what a thread is.
What is Runnable Interface in Java?
The Runnable interface in Java is used for the creation of threads. This interface contains a single method called run(). This method represents the code that will be going to execute whenever the thread starts.
Whenever we create a class that implements the Runnable interface, we define the thread's behavior. The run() method of the class will contain the code that the thread will execute.
Now we know what a Runnable interface in Java is, let us understand how to use it.
Whenever the start() method is called, a new thread is created. The code in the run() method of our RunnableInterfaceExample class is executed on that thread.
The Runnable interface lets you separate the thread behavior from the rest of our application code. By defining the thread's behavior in a separate class that implements Runnable, you can create and manage threads independently of the rest of our application logic. This can make your code more modular and easier to maintain.
Let us try to understand above mentioned steps using an example.
Example
Here is an example of the creation of a thread in Java using the Runnable interface.
Code in Java
public class RunnableInterface implements Runnable {
//Declaring a count variable
private int count;
//run() method this method tells what the thread will do
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println("Ninja " + count + " count: " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//Setter for count variable
public void setCount(int count) {
this.count = count;
}
public static void main(String[] args) {
//Creating object of the interfaces and setting the count
RunnableInterface runnableInterface1 = new RunnableInterface();
runnableInterface1.setCount(1);
RunnableInterface runnableInterface2 = new RunnableInterface();
runnableInterface2.setCount(2);
//Creating object for the thread to use interface’s object
Thread myThread1 = new Thread(runnableInterface1);
Thread myThread2 = new Thread(runnableInterface2);
// Now starting the thread by using start() method
myThread1.start();
myThread2.start();
}
}
You can also try this code with Online Java Compiler
This above code demonstrates how to implement the Runnable interface in Java. This also shows how to create multiple threads that can execute the same run() method with different instance variables. The RunnableInterface class implements the Runnable interface. This means it must implement the run() method. The RunnableInterface class declares a private instance variable called count. This variable is used to identify each thread.
The run() method is defined to print the thread's name. It also prints the current value of the count variable and then sleeps for one second. This method represents what each thread will execute when it starts. The setCount() method is defined to set the value of the count variable for each thread.
Two instances of the RunnableInterface class are created in the main() method. The count values are set to 1 and 2 for these instances. Two Thread objects are created. We are passing corresponding RunnableInterface objects as arguments. The start() method calls on each Thread object. This start() method starts each thread running the run() method.
We might get some exceptions when we use the Runnable interface in Java. Let us discuss them.
Errors encountered when implementing Runnable Interface in Java
When we implement the Runnable interface in Java, there are various exceptions that we might encounter:
InterruptedException: This exception can be thrown when a thread is interrupted while it is sleeping, waiting, or blocking. It is a checked exception, which must be caught or declared in the method signature.
IllegalThreadStateException: This exception can be thrown when a thread is in an illegal state for the requested operation. For example, starting a thread that has already been started will result in this exception.
SecurityException: This exception can be thrown when a security manager is present and does not allow the requested operation. For example, if a thread tries to modify a system property that is not allowed by the security manager, this exception may be thrown.
NullPointerException: This exception can be thrown if a thread attempts to access a null object or call a null method.
IllegalArgumentException: This exception can be thrown if an argument passed to a method is illegal or inappropriate. For example, if an invalid priority value is passed to the setPriority() method of a thread, this exception may be thrown.
OutOfMemoryError: This error can occur if a thread uses too much memory. Also, we can get this error if there is not enough memory available on the Java virtual machine.
If you are implementing the Runnable interface, to define a task that will run in a new thread. Then you can handle the above-mentioned exceptions using the try-catch block inside the run() method. Let us discuss this with an example.
Example
public class RunnableInterfaceExample implements Runnable {
private Thread thread;
//Here we are throwing an exception(Checked Exception)
public void run() throws Exception {
if (myThread == null) {
thread = Thread.currentThread();
}
try {
// Some code that can throw an exception
thread.sleep(1000);
} catch (InterruptedException e) {
// Handling the exception
System.out.println("Thread was interrupted: " + e.getMessage());
} catch (IllegalThreadStateException e) {
// Handling the exception
System.out.println("Caught an IllegalThreadStateException: " + e.getMessage());
}
}
public static void main(String args[]) {
RunnableInterfaceExample runnableInterfaceExample = new RunnableInterfaceExample();
Thread thread = new Thread(runnableInterfaceExample);
thread.start();
}
}
You can also try this code with Online Java Compiler
Main.java:6: error: run() in Main cannot implement run() in Runnable
public void run() throws Exception{
^
overridden method does not throw Exception
1 error
Explanation
In this above example, the run() method a calling the sleep() method of the current thread object thread. This might throw an IllegalThreadStateException if the thread is in an inappropriate state for the requested operation. The exception can be caught using a catch block that specifies the IllegalThreadStateException type. The catch block prints an error message.
Note: The sleep() method of the Thread class can throw an InterruptedException. If in case the thread is interrupted by another thread while it's sleeping, it can throw an InterruptedException. This exception can be caught in a separate catch block.
Thread Class Vs Runnable Interface
There are some differences between Thread class and Runnable Interface in Java that are mentioned below:
Thread Class
Runnable Interface
It is already a concrete class. It implements the Runnable interface. When you create a new class that is extending Thread, that means you are inheriting all of the functionality of the Thread class.
If you are implementing the Runnable interface, you should define the run() method yourself. In the run() method, the code will be executed in the new thread.
If you are extending the Thread class, you cannot extend any other class. Because Java does not allow multiple inheritance.
If you are implementing the Runnable interface, you can still extend other classes. This gives you more flexibility in designing your program.
If you extend the Thread class, it is more suitable when you are designing a class hierarchy that is centered around threads. Also, if you want to define specific behaviors for each type of thread, then you can extend the Thread class.
If you are Implementing, the Runnable interface, it is more suitable when you want to separate the task of running the thread from the other class responsibilities.
It consumes more resources than implementing the Runnable interface, as it creates a new object that has all the properties of a Thread.
Implementing Runnable requires only the creation of a new object that implements the Runnable interface.
Advantages of Using Runnable Interface in Java
The Runnable interface in Java is mainly used to create threads.
The following are the advantages of using Runnable interface Java:
It separates the code that needs to be executed in a separate class. It makes it easier to maintain and manage the codebase. This interface helps to keep the thread logic separate from the rest of the application code, making the code more modular.
Creating threads using the Runnable interface is more efficient than extending the Thread class. When we extend a Thread class, it creates a new object and assigns a new stack to it, which is a bit overhead. However, when try do it by implementing the Runnable interface, it just provides the implementation of the run() method, and there is no extra overhead.
It allows us to create multiple threads from a single implementation. We can create as many threads as we want from a single implementation.
It can help to achieve consistency in our code. It provides a common way to create threads that are used throughout the Java community.
Disadvantages of Using Runnable Interface in Java
Although there are many advantages of using the Runnable interface in Java, there are also some disadvantages of using it in Java:
This has less control over threads than when we extend the Thread class. For example, we cannot directly manipulate the thread's priority or name using the Runnable interface.
It does not provide access to Thread methods. These methods are sleep(), suspend(), resume(), and stop(). These methods can only be accessed using the Thread class.
It is limited to defining the behavior of a single thread. If we want to define more complex behavior that involves multiple threads, we have to use other concurrency constructs such as Executors, Locks, or Semaphores.
When using this interface, we need to ensure that the shared resources accessed by multiple threads are correctly synchronized. If not correctly synchronized, it can lead to race conditions, deadlocks, and other concurrency-related issues.
Frequently Asked Questions
Why use runnable interface in Java?
In Java, a thread is created using the Runnable interface. This interface includes a 'run()' method that executes a runnable item as a separate thread in multi-threading. Java provides the Runnable interface java.lang package.
What is thread class and runnable interface?
The Thread class in Java is a built-in class representing a thread of execution. Developers use the Runnable interface to define the code that a thread can execute. You can assign objects implementing the Runnable interface to a Thread instance for execution.
What type of interface is runnable?
The Runnable interface is functional in Java, introduced in Java 8. Classes implementing the Runnable interface are designed to define a task or unit of work a thread can execute.
Conclusion
This article delves into the concept of the Runnable interface in Java. We have discussed why we use the Runnable interface in Java. Additionally, we explored the advantages and disadvantages of the Runnable interface in Java.
You can check out our other blogs to enhance your knowledge:
We hope this blog helped you to understand the Runnable interface in Java. You can refer to our guided paths on the Coding Ninjas Studio platform. You can also consider our paid courses such asDSA in Javato give your career an edge over others!