Submitting Tasks Individually

Example 23.2 illustrates submitting tasks individually and handling the task result. A Runnable task is defined at (1) that prints a dice value, and a Callable<Integer> task is defined at (2) that returns a dice value. We can of course call the run() and the call() methods to execute the Runnable printDiceValue and the Callable<Integer> diceRoll, respectively, but we would like to execute these tasks in a thread. For this purpose, a fixed thread pool is created at (3) in Example 23.2. Recall that this executor service reuses threads, and tasks may have to wait if all threads are occupied.

The overloaded submit() method of the ExecutorService interface can be used to submit tasks to the executor service. When a task submitted by these methods is executed asynchronously sometime in the future, the status or the result of executing the task is returned in a Future<V> object. The get() method of the Future<V> interface can be used to extract the value contained in a Future<V> object. However, note that the get() method will block the current thread until the task has completed. A timed version of the get(timeout, timeunit) method can also be used if there is a risk of waiting indefinitely.

The Runnable printDiceValue is submitted to the executor service at (4). The get() method, called at (5) to extract the value in the Future<?> object, blocks for the task to complete, if necessary. Since a Runnable does not return a value, the get() method returns the literal value null to indicate successful completion of the task. In this particular case, the type of the object returned is Future<?>, which is parameterized with the ? wildcard to express that it contains an object of some unknown type.

The Callable<Integer> diceValue is submitted to the executor service at (6). The Integer result of executing this callable will be returned in a Future<Integer> object and can be extracted by calling the get() method on this object. The get() method blocks if the task has not completed execution.

Example 23.2 Submitting Tasks and Handling Task Results

Click here to view code image

package executors;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;
public class TaskExecution {
  public static void main(String[] args) {
    // Runnable:
    Runnable printDiceValue = () ->                                        // (1)
      System.out.println(“Execution of Runnable: “
                        + ThreadLocalRandom.current().nextInt(1,7));
    // Callable<V>:
    Callable<Integer> diceRoll =                                           // (2)
        () -> ThreadLocalRandom.current().nextInt(1,7);
    // Executor service:
    ExecutorService exs = Executors.newFixedThreadPool(3);                 // (3)
    try {
      // Executing Runnable in a thread:
      Future<?> rfuture = exs.submit(printDiceValue);                      // (4)
      Object result = rfuture.get();                                       // (5)
      System.out.println(“Result of Runnable: ” + result);
      // Executing Callable<V> in a thread:
      Future<Integer> cfuture = exs.submit(diceRoll);                      // (6)
      Integer diceValue = cfuture.get();                                   // (7)
      System.out.println(“Result of Callable: ” + diceValue);
      // Executing bulk tasks:
      List<Callable<Integer>> callables                                    // (8)
          = List.of(diceRoll, diceRoll, diceRoll);
      List<Future<Integer>> allFutures = exs.invokeAll(callables);         // (9)
      List<Integer> resultList = allFutures.stream()                       // (10)
          .map(future -> {
            try {
              return future.get();
            } catch(InterruptedException | ExecutionException ie) {
              throw new IllegalStateException(ie);
            }
          })
          .toList();
      System.out.println(“Result of invokeAll(): ” + resultList);
      Integer anyResult = exs.invokeAny(callables);                        // (11)
      System.out.println(“Result of invokeAny(): ” + anyResult);
    } catch(InterruptedException | ExecutionException ie) {
      ie.printStackTrace();
    } finally {
      exs.shutdown();
    }
  }
}

Probable output from the program:

Click here to view code image

Execution of Runnable: 4
Result of Runnable: null
Result of Callable: 2
Result of invokeAll(): [1, 3, 6]
Result of invokeAny(): 3