Skip to main content

Runnable

Definition:

At its core, the Runnable interface is a functional interface in Java's java.lang package. It serves as a blueprint for objects representing tasks that can be executed concurrently.

Purpose:

The primary purpose of Runnable is to provide a standardized way to encapsulate the code that needs to run in a separate thread. This abstraction allows for more organized and efficient parallel execution of tasks.

Using Runnable:

Implementing the Runnable Interface:

Let's begin by creating a simple class that implements the Runnable interface.

Example:

public class PrintTask implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " - Task is running: " + i);
}
}
}

In this example, PrintTask is a class implementing Runnable. The run method contains the code to be executed concurrently.

Creating Threads with Runnable:

Now, let's use our PrintTask class to create threads that execute the defined task.

Example:

public class Main {
public static void main(String[] args) {
// Creating an instance of the class implementing Runnable
PrintTask printTask = new PrintTask();

// Creating two threads using the Runnable instance
Thread thread1 = new Thread(printTask);
Thread thread2 = new Thread(printTask);

// Starting the threads
thread1.start();
thread2.start();
}
}

In this example, two threads (thread1 and thread2) are created using the same instance of PrintTask. This demonstrates how a single Runnable instance can be used by multiple threads.

Anonymous Runnable:

If the Runnable implementation is simple and short-lived, you can use an anonymous class for brevity.

Example:

public class Main {
public static void main(String[] args) {
// Creating threads using anonymous Runnable
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " - Task is running: " + i);
}
}
});

Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " - Task is running: " + i);
}
}
});

// Starting the threads
thread1.start();
thread2.start();
}
}

Lambda Expression for Runnable:

With the introduction of lambda expressions in Java 8, the syntax for implementing Runnable becomes even more concise.

Example:

public class Main {
public static void main(String[] args) {
// Creating threads using lambda expression for Runnable
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " - Task is running: " + i);
}
});

Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " - Task is running: " + i);
}
});

// Starting the threads
thread1.start();
thread2.start();
}
}

The use of lambda expressions makes the code concise and expressive, especially for short Runnable implementations.

Real-Life Example: Download Manager

Let's consider a real-world scenario where Runnable can be applied. Imagine a simple download manager that needs to download multiple files concurrently.

Example Code:

import java.util.List;

public class DownloadManager {
public static void main(String[] args) {
List<String> filesToDownload = List.of("File1", "File2", "File3", "File4", "File5");

for (String file : filesToDownload) {
// Creating a thread for each download task using lambda expression
Thread downloadThread = new Thread(() -> {
System.out.println("Downloading " + file + " on thread: " + Thread.currentThread().getName());
// Simulate download process
try {
Thread.sleep(2000); // Simulating download time
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Download completed for " + file);
});
downloadThread.start();
}
}
}

Expected Output:

The output may vary due to the concurrent nature of threads, but a sample output might look like:

Downloading File1 on thread: Thread-0
Downloading File2 on thread: Thread-1
Downloading File3 on thread: Thread-2
Downloading File4 on thread: Thread-3
Downloading File5 on thread: Thread-4
Download completed for File1
Download completed for File2
Download completed for File3
Download completed for File4
Download completed for File5

Please note that the exact order of thread execution may vary, as threads run concurrently.

tip

Implement the Runnable interface when creating threads to encapsulate the code that should run concurrently. This promotes a cleaner separation of concerns.

Challenge Question

Compare the use of Runnable with extending the Thread class for creating concurrent tasks. In what scenarios would you prefer one approach over the other?