Return Value of Callable Interface in Java
The Callable interface in Java returns a value of a specified type when a task is executed. Unlike Runnable, which doesn't return any value, Callable's call() method can return a result or throw an exception. This feature is particularly useful in concurrent programming when you need to perform tasks asynchronously and obtain computed results or handle exceptions, making it a valuable choice for many multi-threading scenarios.
Why use a Callable interface in Java?
In Java, the Callable interface is used primarily for its role in concurrent programming. It's part of the java.util.concurrent package and provides a way to execute tasks asynchronously and retrieve their results.
The main advantage of using Callable over Runnable is that Callable tasks can return a result and throw exceptions, while Runnable tasks cannot. This makes Callable especially useful in scenarios where you need to execute tasks in parallel and obtain their computed values or handle exceptions that may occur during execution.
When working with multi-threading, thread pools, or asynchronous programming in Java, Callable allows for better error handling and result retrieval, making it a valuable tool for building efficient and robust concurrent applications.
Also see, Swap Function in Java
Implementation of Java Callable Interface
We have discussed the definition, syntax and features of the callable interface. Now, we will see how to implement this.
Java
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.Future;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ExecutionException;
public class NinjaTest implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(50);
// Return the current thread
return Thread.currentThread().getName();
}
// Main method
public static void main(String args[]){
ExecutorService executor = Executors.newFixedThreadPool(5);
// Creating a list for the Future object
List<Future<String>> list = new ArrayList<Future<String>>();
// Creating an instance named NinjaTest
Callable<String> callable = new NinjaTest();
for(int i = 0; i < 10; i++){
Future<String> future = executor.submit(callable);
list.add(future);
}
for(Future<String> fut : list){
try {
// Print the return value of Future
System.out.println(fut.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
executor.shutdown();
}
}
You can also try this code with Online Java Compiler
Run Code
Output:
pool-1-thread-1
pool-1-thread-2
pool-1-thread-3
pool-1-thread-4
pool-1-thread-5
pool-1-thread-3
pool-1-thread-1
pool-1-thread-5
pool-1-thread-2
pool-1-thread-4
Explanation:
In the above example,
- We have created an object of ExecutorService in the main method inherited from the Executors utility class.
- Next, we have created a list variable of list type to hold the object of the Future associated with Callable.
- In the next step, we created an instance NinjaTest using the Callable class.
- Inside the for loop, we have submitted the Callable tasks that will be executed by the thread pool using the submit() method.
- We will add the Future to the list and receive a return value using Future.
- We will print the return value inside the for loop under the try block. Here, you can notice the delay time. The compiler will delay because Future.get() waits for the task to get completed.
- At last, we will shut down the executor.
Features of Java Callable Interface
There are many features of the callable interface. Let's discuss them.
- The entire code for the callable class is present in the single function "call()".
- The callable class is a SAM (Single Abstract Method) type interface and can be executed in a lambda expression.
- A callable interface's call() method can return any type of object.
- The get() function in the callable interface is also known as the blocking call, and it keeps blocking till the computation is finished.
- The FutureTask object's cancel() method can stop the computation also.
Examples of Callable Interface in Java
Example 1:
Java
import java.util.concurrent.*;
public class CallableExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<Integer> task = () -> {
TimeUnit.SECONDS.sleep(1);
return 123;
};
Future<Integer> future = executor.submit(task);
try {
System.out.println("Future result: " + future.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
executor.shutdown();
}
}
You can also try this code with Online Java Compiler
Run Code
Output
Future result: 123
Example 2:
Java
import java.util.concurrent.*;
public class CallableDatabaseQuery {
static class DatabaseQuery implements Callable<String> {
private final String query;
public DatabaseQuery(String query) {
this.query = query;
}
@Override
public String call() throws Exception {
// Simulate database access time
TimeUnit.SECONDS.sleep(2);
return "Result of query: " + query;
}
}
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<String> result1 = executor.submit(new DatabaseQuery("SELECT * FROM users"));
Future<String> result2 = executor.submit(new DatabaseQuery("SELECT * FROM products"));
try {
System.out.println(result1.get());
System.out.println(result2.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
executor.shutdown();
}
}
You can also try this code with Online Java Compiler
Run Code
Output:
Result of query: SELECT * FROM users
Result of query: SELECT * FROM products
Read more about Object-Oriented Programming
Frequently Asked Questions
Can we create a thread using a Callable interface?
Yes, you can create a thread using a Callable interface in Java, but not directly. Instead, you submit a Callable task to an ExecutorService, which manages thread creation and execution, returning a Future object to handle the result.
What is the difference between Callable interface and runnable interface in Java?
Callable and Runnable are interfaces in Java for defining tasks that can be executed asynchronously. Callable can return results or throw exceptions, whereas Runnable cannot. Future is a container for the result of an asynchronous task, allowing you to retrieve the result when it's ready or handle exceptions.
When should we use Callable Java?
Use Callable in Java when you need to execute tasks that return results or throw exceptions in multithreaded environments, offering better control and error handling.
What is the difference between Callable and future in Java?
Callable defines tasks, while Future represents the result of asynchronous computation. Callable is a functional interface, while Future is an interface for managing asynchronous computation results and completion status.
Conclusion
This article discusses the topic of the callable interface in Java in detail. We have seen the callable interface's definition, syntax, and features in Java. Along with this, we saw the example code with output and a proper explanation.
We hope this blog has helped you enhance your knowledge of the callable interface in Java. If you want to learn more, then check out our articles.
To learn more about Data Structures and Algorithms, you can enroll in our course on DSA in Java.