Java Callable Future Example

One of the benefits of the Java executor framework is that we can run concurrent tasks that may return a single result after processing the tasks. The Java Concurrency API achieves this with the following two interfaces Callable and Future. In this tutorial, we will learn to execute …

Java_Multithreading

One of the benefits of the Java executor framework is that we can run concurrent tasks that may return a single result after processing the tasks. The Java Concurrency API achieves this with the following two interfaces Callable and Future.

In this tutorial, we will learn to execute Callable tasks (which return a result of type Future after execution) using ExecutorService implementations in this simple Callable Future example.

1. Java Callable and Future Interfaces

1.1. Callable

In Java concurrency, Callable represents a task that returns a result. Executors can run callable tasks – concurrently. Since Java 8, it is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.

Callable interface has the call() method. In this method, we have to implement the logic of a task. The Callable interface is a parameterized interface, meaning we have to indicate the type of data the call() method will return.

@FunctionalInterface
public interface Callable<V> {
/**
 * Computes a result, or throws an exception if unable to do so.
 *
 * @return computed result
 * @throws Exception if unable to compute a result
 */

V call() throws Exception;
}

2.2. Future

Future interface has methods to obtain the result generated by a Callable object and manage its state. It represents the result of an asynchronous computation. The result can only be retrieved using method get() when the computation has been completed, blocking if necessary until it is ready.

The cancellation of a task is performed by the cancel() method. Once a computation has been completed, the computation cannot be canceled.

public interface Future<V> 
{
  boolean cancel(boolean mayInterruptIfRunning);
 
  boolean isCancelled();
 
  boolean isDone();
 
  V get() throws InterruptedException, ExecutionException;
 
  V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

2. Java Callable Future Example

In this example, we are executing a task that returns its name when it’s completed. We will use ExecutorService to execute this task and print its name in main thread after it has been completed.

The Future.get() is used for blocking the main thread execution until the corresponding task submitted to the executor is not completed. It can, optionally, take a timeout period after which it will unblock with a TimeOutException.

import java.time.LocalDateTime;
import java.util.concurrent.*;

public class CallableFutureExample {
  public static void main(String[] args) throws ExecutionException,
      InterruptedException, TimeoutException {

    ExecutorService executor = Executors.newFixedThreadPool(1);
    Future<String> future = executor.submit(new Work("Demo-Task"));

    String completedThread = future.get(10, TimeUnit.SECONDS);

    System.out.println("Thread completed : " + completedThread);
  }
}

class Work implements Callable<String> {
  private final String name;

  public Work(String name) {this.name = name;}

  @Override
  public String call() {
    System.out.println("Task [" + name + "] executed on : " + LocalDateTime.now().toString());
    return name;
  }
}

Program output.

Task [Demo-Task] executed on : 2022-08-07T15:57:33.372000500
Thread completed : Demo-Task

Here we sent a Callable object to be executed in an executor using the submit() method. This method receives a Callable object as a parameter and returns a Future object that we can use with two main objectives –

  1. We can control the status of the task – we can cancel the task and check if it has finished. For this purpose, we can use the isDone() method to check if the tasks had finished.
  2. We can get the result returned by the call() method. For this purpose, we have used the get() method. This method waits until the Callable object has finished the execution of the call() method and has returned its result.

    If the thread is interrupted while the get() method is waiting for the result, it throws an InterruptedException exception. If the call() method throws an exception, this method throws an ExecutionException exception.

3. Conclusion

In this tutorial, we learned the basics of the Callable and Future interfaces and how to execute callable tasks with ExecutorService. We learned to control the execution using the isDone(), cancel() and get() methods.

Happy Learning !!

Leave a Comment

  1. I just saw in Java 8 ,The Future‘s method get(longtimeout,TimeUnitunit)shouldt hrows TimeoutException if the wait timed out, not return null .

    Reply
    • Yep, you are right it should throw the TimeoutException and not null. Here is the implementation.

          public V get(long timeout, TimeUnit unit)
              throws InterruptedException, ExecutionException, TimeoutException {
              if (unit == null)
                  throw new NullPointerException();
              int s = state;
              if (s <= COMPLETING &&
                  (s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)
                  throw new TimeoutException();
              return report(s);
          }
      
      Reply
  2. Thank you for the great article.
    But, how to run task periodically (every n seconds) and retrieve some result, which is needed in further processing? Is it wise to use in indefinite while(true) loop, the method schedule (Callable task, long delay, TimeUnit timeunit)?

    Reply
  3. Here is the code

    class TestTRejectedExecutionHandler implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
    try {
    System.out.println(“Rejected Execution Handler For Thread ” + Thread.currentThread().getName());
    Thread.sleep(1000);
    } catch (Exception e2) {
    // TODO: handle exception
    }
    executor.execute(r);
    }
    }

    class TestTTask implements Callable {
    @Override
    public String call() {
    try {
    Thread.sleep(1000);
    } catch (Exception e) {
    // TODO: handle exception
    }
    return Thread.currentThread().getName();
    }
    }

    public class TestT {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
    BlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(
    1);
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 2,
    1000, TimeUnit.MILLISECONDS, arrayBlockingQueue,
    new TestTRejectedExecutionHandler());

    for (int iLoop = 0; iLoop < 100; iLoop++) {
    Future future = threadPoolExecutor.submit(new TestTTask());
    System.out.println(future.get());
    }
    }
    }

    Reply
  4. Here is my Example.

    In this If i call future.get(), then rejectedExecution doesn’t get executed, but if comment that line(future.get()) then it is getting executed.

    Please Suggest a way forward.

    Reply
    • Hi Dushyant,
      get() is blocking call so calling that method after submitting will not give better result since you are waiting the just submitted task. Replace the loop with the below code instead.

       List<Future<String>> list = new ArrayList<>();
              for (int iLoop = 0; iLoop < 10; iLoop++) {
                  Future<String> future = threadPoolExecutor.submit(new TestTTask());
                  list.add(future);
              }
      //getting the results of all submitted task
              for(Future<String> future:list){
                  System.out.println("Thread Name: "+future.get());
              }
      
      
      Reply
  5. Hello

    How would you handle Rejected Task if i use ArrayBlockingQueue and choose to implement my own RejectedExecutionHandler Class.

    Dushyant Sapra

    Reply
  6. Very nice article about Future, Callable and Executor. I wandered here and there for basic information and use, but didn’t find as easiest as this. Thanks Lokesh. Thanks a lot.

    Reply
  7. very very useful information, to know any new subject I will first search in your site. if I didnot find then I go for google search.

    Reply

Leave a Comment

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.