Callable vs Future in Java

Last Updated : 25 Apr, 2026

In Java, multithreading allows tasks to run concurrently, improving performance and responsiveness. Traditionally, developers used the Runnable interface to define tasks, but it has two major limitations: it cannot return a result and cannot throw checked exceptions. To overcome these, Java introduced the Callable and Future interfaces in Java 5.

  • Callable executes a task and returns a result with exception handling
  • Future represents the result of a Callable task and retrieves it later

Callable Interface

The Callable interface represents a task that can return a result and throw checked exceptions. It is an alternative to Runnable when a task needs to produce an output.

  • Defines the call() method for task execution
  • Allows checked exceptions during execution
  • Commonly used with Future to retrieve results
Java
import java.util.concurrent.*;

public class CallableExample {
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newSingleThreadExecutor();

        Callable<Integer> task = () -> {
            int sum = 0;
            for (int i = 1; i <= 5; i++) sum += i;
            return sum;  // returns result
        };

        Future<Integer> future = executor.submit(task);

        System.out.println("Result: " + future.get()); 
        executor.shutdown();
    }
}

Output
Result: 15

Explanation: A Callable task is submitted to the executor. It calculates the sum of numbers from 1 to 5 and returns the result. The result is retrieved using future.get() after the task finishes.

Future Interface

The Future interface represents the outcome of an asynchronous task and allows you to interact with it after submission to an ExecutorService.

  • Acts as a handle to track task status
  • get() retrieves the result (blocks until completion)
  • isDone() checks if the task has finished
Java
import java.util.concurrent.*;

public class CallableFutureExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newSingleThreadExecutor();

        Future<Integer> future = executor.submit(() -> 10 + 20);

        try {
            Integer result = future.get(); // waits but returns instantly
            System.out.println("Result: " + result);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            executor.shutdown();
        }
    }
}

Output
Result: 30

Explanation: This code creates a single-thread executor to run a task asynchronously using Callable. The task calculates the sum of 10 and 20, and the result is stored in a Future object. Using future.get(), the program retrieves the result (30), and finally shuts down the executor to free resources.

Callable vs Future

Table showing difference between callable and future.

FeatureCallableFuture
PurposeRepresents a task that returns a resultRepresents the result of an asynchronous task
Return TypeReturns a result when executedHolds the result returned by a Callable
Defined Injava.util.concurrent packagejava.util.concurrent package
ExecutionSubmitted to ExecutorServiceReturned by ExecutorService.submit()
MethodsHas one method call()Has methods like get(), isDone(), cancel()
Exception HandlingCan throw checked exceptionsHandles results and exceptions after execution
UsageDefines what to executeControls, monitors, and retrieves the result of a task
Comment