Java Interview Questions
Java
Web DevelopmentBackendQuestion 21
What is the difference between the 'Runnable' and 'Callable' interfaces?
Answer:
In Java, both Runnable and Callable are interfaces designed for representing tasks that can be executed by a thread or an executor service. However, they have some key differences, mainly in their method signatures and the way they handle results and exceptions. Here’s a detailed comparison:
Runnable Interface
Definition: The Runnable interface is a functional interface that is designed to represent a task that can be executed by a thread.
Method:
void run(): Therunmethod does not return any value and does not throw any checked exceptions.
Example:
public class RunnableExample implements Runnable {
@Override
public void run() {
System.out.println("Task is running.");
}
public static void main(String[] args) {
RunnableExample task = new RunnableExample();
Thread thread = new Thread(task);
thread.start();
}
}
Callable Interface
Definition: The Callable interface is a generic interface that is part of the java.util.concurrent package. It is designed to represent a task that can be executed by a thread and can return a result and throw a checked exception.
Method:
V call() throws Exception: Thecallmethod returns a result of typeVand can throw a checked exception.
Example:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class CallableExample implements Callable<Integer> {
@Override
public Integer call() throws Exception {
return 123;
}
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
CallableExample task = new CallableExample();
Future<Integer> future = executor.submit(task);
try {
Integer result = future.get();
System.out.println("Result: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
executor.shutdown();
}
}
}
Key Differences
-
Return Type:
- Runnable: The
runmethod does not return a result. - Callable: The
callmethod returns a result of typeV.
- Runnable: The
-
Exception Handling:
- Runnable: The
runmethod cannot throw checked exceptions. - Callable: The
callmethod can throw checked exceptions.
- Runnable: The
-
Usage Context:
- Runnable: Typically used when you do not need a result from the task and do not need to handle checked exceptions. Often used with
Threadclass directly. - Callable: Used when you need a result from the task or need to handle checked exceptions. Often used with executor services and futures.
- Runnable: Typically used when you do not need a result from the task and do not need to handle checked exceptions. Often used with
-
Integration with Executors:
- Runnable: Can be submitted to an
ExecutorServiceusingsubmit(Runnable task), but will return aFuture<?>with anullresult. - Callable: Can be submitted to an
ExecutorServiceusingsubmit(Callable<V> task), and will return aFuture<V>with the result of the computation.
- Runnable: Can be submitted to an
When to Use Each
-
Runnable: Use when the task does not need to return any result or throw any checked exceptions. Suitable for simple tasks that can be executed in a new thread or submitted to an executor.
Example:
ExecutorService executor = Executors.newSingleThreadExecutor(); executor.submit(new Runnable() { @Override public void run() { System.out.println("Runnable task executed."); } }); executor.shutdown(); -
Callable: Use when the task needs to return a result or throw checked exceptions. Suitable for tasks that are more complex and require a return value or need to handle potential exceptions during execution.
Example:
ExecutorService executor = Executors.newSingleThreadExecutor(); Future<Integer> future = executor.submit(new Callable<Integer>() { @Override public Integer call() throws Exception { return 456; } }); try { Integer result = future.get(); System.out.println("Callable task result: " + result); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } finally { executor.shutdown(); }
Conclusion
Both Runnable and Callable are used to represent tasks in Java, but they serve different purposes. Runnable is simpler and is used when no result or checked exception handling is needed. Callable is more versatile, providing a way to return results and handle exceptions. Understanding these differences helps you choose the appropriate interface for your concurrent task execution needs.