🎓 Top 15 Udemy Courses (80-90% Discount): My Udemy Courses - Ramesh Fadatare — All my Udemy courses are real-time and project oriented courses.
▶️ Subscribe to My YouTube Channel (178K+ subscribers): Java Guides on YouTube
▶️ For AI, ChatGPT, Web, Tech, and Generative AI, subscribe to another channel: Ramesh Fadatare on YouTube
Introduction
The Runnable interface in Java is a functional interface designed for classes whose instances are intended to be executed by a thread. It provides a way to define a task that can be executed concurrently. This interface is often used in conjunction with the Thread class or with executors in the java.util.concurrent package.
Table of Contents
- Overview of Runnable Interface
- Implementing Runnable
- Running a Runnable
- Example: Implementing and Running Runnable
- Using Runnable with Executors
- Using Runnable with Lambda Expressions
- Advantages of Using Runnable
- Conclusion
1. Overview of Runnable Interface
The Runnable interface is a single-method interface that defines the run method. This method is meant to contain the code that constitutes the task to be executed by a thread.
Runnable Interface:
public interface Runnable {
void run();
}
2. Implementing Runnable
To create a task using the Runnable interface, a class needs to implement the Runnable interface and provide an implementation for the run method.
Example:
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable is running.");
}
}
3. Running a Runnable
There are two common ways to run a Runnable:
- Using the
Threadclass. - Using an executor from the
java.util.concurrentpackage.
Using the Thread Class
Example:
public class RunnableExample {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start(); // Start the thread
}
}
4. Example: Implementing and Running Runnable
Let's create a complete example to demonstrate how to implement and run a Runnable.
Example:
class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " is running. Count: " + i);
try {
Thread.sleep(1000); // Simulate some work with sleep
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class RunnableExample {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread1 = new Thread(myRunnable);
Thread thread2 = new Thread(myRunnable);
thread1.start();
thread2.start();
}
}
Output:
Thread-0 is running. Count: 0
Thread-1 is running. Count: 0
Thread-0 is running. Count: 1
Thread-1 is running. Count: 1
Thread-0 is running. Count: 2
Thread-1 is running. Count: 2
Thread-0 is running. Count: 3
Thread-1 is running. Count: 3
Thread-0 is running. Count: 4
Thread-1 is running. Count: 4
Explanation:
- The
MyRunnableclass implements theRunnableinterface and overrides therunmethod. - Two
Threadobjects are created, each with the sameMyRunnableinstance. - Both threads are started, and they run concurrently, each executing the
runmethod.
5. Using Runnable with Executors
The java.util.concurrent package provides the ExecutorService interface and various implementations to manage a pool of threads. Using an executor is a more flexible and efficient way to manage multiple threads.
Example:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " is running. Count: " + i);
try {
Thread.sleep(1000); // Simulate some work with sleep
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class RunnableWithExecutorExample {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
MyRunnable myRunnable = new MyRunnable();
executorService.submit(myRunnable);
executorService.submit(myRunnable);
executorService.shutdown();
}
}
Output:
pool-1-thread-1 is running. Count: 0
pool-1-thread-2 is running. Count: 0
pool-1-thread-1 is running. Count: 1
pool-1-thread-2 is running. Count: 1
pool-1-thread-1 is running. Count: 2
pool-1-thread-2 is running. Count: 2
pool-1-thread-1 is running. Count: 3
pool-1-thread-2 is running. Count: 3
pool-1-thread-1 is running. Count: 4
pool-1-thread-2 is running. Count: 4
Explanation:
- An
ExecutorServiceis created with a fixed thread pool of 2 threads. - Two tasks (instances of
MyRunnable) are submitted to the executor. - The executor manages the execution of the tasks, and the threads from the pool execute the
runmethod concurrently.
6. Using Runnable with Lambda Expressions
With Java 8, you can use lambda expressions to create instances of functional interfaces like Runnable. This approach makes the code more concise and readable.
Example:
public class RunnableWithLambdaExample {
public static void main(String[] args) {
Runnable task = () -> {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " is running. Count: " + i);
try {
Thread.sleep(1000); // Simulate some work with sleep
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread1 = new Thread(task);
Thread thread2 = new Thread(task);
thread1.start();
thread2.start();
}
}
Output:
Thread-0 is running. Count: 0
Thread-1 is running. Count: 0
Thread-0 is running. Count: 1
Thread-1 is running. Count: 1
Thread-0 is running. Count: 2
Thread-1 is running. Count: 2
Thread-0 is running. Count: 3
Thread-1 is running. Count: 3
Thread-0 is running. Count: 4
Thread-1 is running. Count: 4
Explanation:
- A
Runnabletask is created using a lambda expression. - Two
Threadobjects are created, each with the sameRunnabletask. - Both threads are started, and they run concurrently, each executing the
runmethod defined in the lambda expression.
7. Advantages of Using Runnable
- Decoupling Task from Execution: The
Runnableinterface allows the separation of the task from the thread that executes it. - Flexibility: A class can implement
Runnableand extend another class, providing more flexibility in design. - Reuse with Executors:
Runnabletasks can be reused with executor services, providing better thread management and resource utilization. - Lambda Expressions: With Java 8 and above, lambda expressions can be used to create
Runnableinstances, making the code more concise and readable.
8. Conclusion
The Runnable interface in Java provides a simple and flexible way to define tasks that can be executed by threads. By implementing the Runnable interface, you can create tasks that can run concurrently, either by using the Thread class or by using executors from the java.util.concurrent package. With the addition of lambda expressions in Java 8, creating and using Runnable tasks has become even more straightforward and concise. This interface is a fundamental part of multithreading in Java and is essential for writing concurrent applications.
Happy coding!
Comments
Post a Comment
Leave Comment