Introduction
Callable
and Future
are part of the java.util.concurrent
package and are used for concurrent programming. Callable
is similar to Runnable
, but it can return a result and throw a checked exception. Future
represents the result of an asynchronous computation and provides methods to check if the computation is complete, to wait for its completion, and to retrieve the result.
Key Points:
- Callable: An interface that defines a task that returns a result and can throw a checked exception.
- Future: An interface that represents the result of an asynchronous computation.
- Concurrency Utilities: Part of the
java.util.concurrent
package, which provides robust concurrency utilities.
Table of Contents
- Creating a Callable Task
- Submitting Callable Tasks to ExecutorService
- Using Future to Retrieve Results
- Comprehensive Example
- Real-World Analogy
- Conclusion
1. Creating a Callable Task
A Callable
task is similar to a Runnable
task, but it returns a result and can throw a checked exception.
Example:
import java.util.concurrent.Callable;
public class CallableTask implements Callable<Integer> {
private int number;
public CallableTask(int number) {
this.number = number;
}
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1; i <= number; i++) {
sum += i;
Thread.sleep(100); // Simulate time-consuming task
}
return sum;
}
}
2. Submitting Callable Tasks to ExecutorService
You can submit a Callable
task to an ExecutorService
and get a Future
object that represents the result of the computation.
Example:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class CallableFutureExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3);
CallableTask task = new CallableTask(10);
Future<Integer> future = executor.submit(task);
executor.shutdown();
}
}
3. Using Future to Retrieve Results
The Future
interface provides methods to check if the computation is complete, wait for its completion, and retrieve the result.
Example:
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
public class CallableFutureExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3);
CallableTask task = new CallableTask(10);
Future<Integer> future = executor.submit(task);
executor.shutdown();
try {
Integer result = future.get(); // Wait for the task to complete and retrieve the result
System.out.println("Result: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
4. Comprehensive Example
Example: Using Callable and Future
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;
import java.util.ArrayList;
import java.util.List;
class CallableTask implements Callable<Integer> {
private int number;
public CallableTask(int number) {
this.number = number;
}
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1; i <= number; i++) {
sum += i;
Thread.sleep(100); // Simulate time-consuming task
}
return sum;
}
}
public class CallableFutureExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3);
List<Future<Integer>> futures = new ArrayList<>();
for (int i = 1; i <= 5; i++) {
CallableTask task = new CallableTask(i * 10);
Future<Integer> future = executor.submit(task);
futures.add(future);
}
executor.shutdown();
for (Future<Integer> future : futures) {
try {
Integer result = future.get(); // Wait for the task to complete and retrieve the result
System.out.println("Result: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
}
Output:
Result: 55
Result: 210
Result: 465
Result: 820
Result: 1275
5. Real-World Analogy
Consider a scenario where multiple students (threads) are given different assignments (tasks) to complete. Each student works on their assignment and once they finish, they submit it to the teacher (ExecutorService). The teacher then collects all the completed assignments (Future) and checks the results.
6. Conclusion
Callable
and Future
are powerful interfaces in the java.util.concurrent
package that provide a way to execute tasks asynchronously and retrieve their results. By using these interfaces, you can manage complex concurrent tasks more efficiently and handle their results in a structured manner.