In Java, the Callable
interface and Future
interface are used in conjunction to run tasks asynchronously in a separate thread and fetch the result of the computation once it is complete. This is particularly useful when you need the task to return a result or throw a checked exception.
Here’s a step-by-step guide to how you can use Callable
and Future
:
1. Step: Callable Interface
The Callable
interface allows you to define a task that returns a result. Unlike Runnable
, which does not return any value, Callable
has a generic call()
method that can return a value or throw an exception.
package org.kodejava.util.concurrent;
import java.util.concurrent.Callable;
public class MyTask implements Callable<Integer> {
@Override
public Integer call() throws Exception {
// Perform some computation
int result = 42; // Example computation result
return result; // Return the result
}
}
2. Step: Use ExecutorService to Execute Callable
To execute a Callable
, you need an ExecutorService
. The ExecutorService
can submit the task and return a Future
object.
package org.kodejava.util.concurrent;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Main {
public static void main(String[] args) {
// Create an ExecutorService
ExecutorService executor = Executors.newSingleThreadExecutor();
// Create a Callable task
Callable<Integer> task = new MyTask();
try {
// Submit the task for execution
Future<Integer> future = executor.submit(task);
// Do other tasks in the main thread (if any)
// Get the result from the Future
Integer result = future.get(); // This will block until the task is complete
System.out.println("Result from the task: " + result);
} catch (Exception e) {
e.printStackTrace();
} finally {
// Shut down the executor
executor.shutdown();
}
}
}
3. Key Points to Remember
Callable
vsRunnable
:Callable
returns a result and can throw a checked exception.Runnable
doesn’t return a result and cannot throw a checked exception.
Future
:Future.get()
blocks until the task is complete and the result is available.- You can use
isDone()
to check if the task is finished without blocking.
- Shutting Down the Executor:
- Always remember to shut down the
ExecutorService
to release resources.
- Always remember to shut down the
4. Example with Multiple Callable Tasks
If you have multiple tasks to run in parallel, you can submit them all to the executor and retrieve results using Future
for each task.
package org.kodejava.util.concurrent;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class MultipleTask {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3); // 3 threads
List<Callable<String>> tasks = new ArrayList<>();
tasks.add(() -> "Task 1 result");
tasks.add(() -> "Task 2 result");
tasks.add(() -> "Task 3 result");
try {
// Submit all tasks and get a list of Futures
List<Future<String>> futures = executor.invokeAll(tasks);
// Process results
for (Future<String> future : futures) {
System.out.println("Result: " + future.get()); // Blocking call
}
} catch (Exception e) {
e.printStackTrace();
} finally {
executor.shutdown();
}
}
}
5. Timeout with Future.get()
If you want to prevent indefinite blocking, you can specify a timeout when calling get()
.
Integer result = future.get(5, TimeUnit.SECONDS); // Waits for 5 seconds
6. Asynchronous Checking for Completion
Instead of blocking with get()
, you can check periodically if the task is done.
if (future.isDone()) {
System.out.println("Task completed! Result: " + future.get());
} else {
System.out.println("Task is still running...");
}
7. Output Example
Here is an example of output you might see when running the first full example:
Result from the task: 42
When to Use Callable and Future
- When computations are costly and need to run in a background thread.
- When you need a result or want to handle exceptions from tasks.
- When you need to execute multiple tasks and aggregate their results.
This approach is powerful when working with concurrent programming in Java! If you need further clarification or examples, feel free to ask.
- How do I secure servlets with declarative security in web.xml - April 24, 2025
- How do I handle file uploads using Jakarta Servlet 6.0+? - April 23, 2025
- How do I serve static files through a Jakarta Servlet? - April 23, 2025