Defining Tasks That Return a Result

Implementations of the java.util.concurrent.Callable<V> functional interface represent tasks that are designed to be executed by threads—analogous to implementations of the java.lang.Runnable functional interface. Whereas we can create and start a thread by passing a Runnable to a constructor of the Thread class, this is not possible with a Callable<V> implementation, as Thread constructors do not accept a Callable<V> object. In order to execute an implementation of the Callable<V> functional interface as a task in a thread, we can use an executor service—a topic which we explore thoroughly later (p. 1436).

In contrast to the Runnable interface, the Callable<V> interface is generic. As opposed to the void run() method of the Runnable interface, the call() method of the Callable<V> interface returns a result from the task it represents and can throw checked exceptions. As it is a functional interface, the implementation of its sole method call() can be provided by a lambda expression.

An executor service provides bulk execution of tasks grouped in a collection using its methods invokeAny() and invokeAll() (p. 1439). Such bulk tasks can only be implemented as Callable<V> tasks, and not as Runnable tasks.

Typically, a Runnable is used for long-running tasks, such as a server, whereas a Callable<V> is a one-shot task that needs to compute and return a result.

The code at (1) implements a Callable<Integer> that simulates a dice using a Random object (§8.7, p. 482). The method call() is invoked directly on this implementation at (2) to roll the dice. Later we will see how we can obtain the value of a dice roll asynchronously in a thread using an executor service (p. 1438).

Click here to view code image

Random rng = new Random();
Callable<Integer> dice = () -> rng.nextInt(1,7);  // (1)
try {
  Integer diceValue = dice.call();     // (2)
  System.out.println(diceValue);       // Prints a value in the interval [1,6].
} catch (Exception ex) {
  ex.printStackTrace();
}

The following method is defined in the Callable<V> functional interface:

V call() throws Exception

Computes a result, or throws an exception if unable to do so.