Callable and Future

Introduction to Callable and Future

Welcome back! In the previous lesson, we explored how to manage threads using Executors and Runnable. Now, we'll build on that foundation by introducing two advanced tools in Java's concurrency toolkit: Callable and Future. These components allow tasks to return results and handle exceptions, offering greater flexibility than Runnable. By the end of this lesson, you'll be able to handle asynchronous computations more effectively in your Java applications.

What You'll Learn

In this lesson, you'll gain an understanding of how to:

  • Use the Future interface to manage and retrieve results from asynchronous tasks.
  • Implement the Callable interface for tasks that return values or throw exceptions.
  • Submit Callable tasks to an ExecutorService and retrieve results using Future.

These concepts will greatly enhance your ability to handle asynchronous operations.

Understanding Future

The Future interface represents the result of an asynchronous computation. When you submit a task to an ExecutorService, it returns a Future object, which serves as a placeholder for the task's result. The Future provides several methods to monitor the status of the task, retrieve its result, and even cancel the task if necessary.

Let’s now look at an example that demonstrates submitting a Runnable task and monitoring its status using Future.

Future<?> future = executor.submit(() -> {
    System.out.println("Task executed by " + Thread.currentThread().getName());
});

if (!future.isDone()) {
    System.out.println("Task is still running...");
}

executor.shutdown();

In this example:

  • The task is submitted using the submit() method, which returns a Future object. Unlike execute(), which does not return anything, submit() gives you more control over the task, allowing you to track its progress and retrieve a result if needed.

  • We use the isDone() method to check whether the task has completed execution. If the task is still running, it prints a message. future.isDone() checks if a Future task is complete without blocking the thread, unlike future.get(), which waits until the task finishes. It allows you to poll the task's status and act accordingly.

The Future object provides additional flexibility compared to execute() because it allows you to manage the task more effectively, especially when it involves results or long-running operations.

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal