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()
: Therun
method 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
: Thecall
method returns a result of typeV
and 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
run
method does not return a result. - Callable: The
call
method returns a result of typeV
.
- Runnable: The
-
Exception Handling:
- Runnable: The
run
method cannot throw checked exceptions. - Callable: The
call
method 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
Thread
class 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
ExecutorService
usingsubmit(Runnable task)
, but will return aFuture<?>
with anull
result. - Callable: Can be submitted to an
ExecutorService
usingsubmit(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.