Java Callable And Future With Examples

In this post we’ll see two of the interesting features of the concurrent API, Callable and Future in Java.

Callable in Java

Consider a scenario where you have a big computation and you want to split it into multiple sub-tasks which are executed by multiple threads with each thread working on a part of the task. Once all the threads are finished with their tasks you can combine the partial results to get the result of the computation.

Designing this scenario with Runnable makes it difficult as Runnable doesn’t return a result. That shortcoming is filled by Callable in Java as it can return a result and may throw an exception.

Callable interface

Callable interface in Java has a single method call() which computes a result and returns it or throws an exception if unable to do so.

public interface Callable<V> {
    V call() throws Exception;
}

So, you need to implement call() method to provide the task that has to be implemented by a thread as an asynchronous computation. Here is a simple example of Callable implementation-

Callable<String> callable = new Callable<String>() {
  public String call() {
    return "Value returned from Callable";
  }
};

Since Callable is a functional interface it can also be implemented as a lambda expression.

Callable<String> callable = ()->{
  return "Value returned from Callable";
};

Running a Callable task using ExecutorService

To execute a Callable, submit() method of ExecutorService is used.

<T> Future<T> submit(Callable<T> task)- Submits a callable task which returns value for execution and returns a Future representing the pending results of the task.

When a callable task is submitted it is executed in its own thread asynchronously. It is not known when the result of that asynchronous computation will be available, all we know is it will be available in some future. Thus an appropriately named interface Future represents the return value of the callable task.

Java Callable and Future example

Here is a simple example showing how callable task is submitted using ExecutorService and how to obtain the returned value using Future.

public class CallableDemo {
  public static void main(String[] args) {
    ExecutorService executor = Executors.newSingleThreadExecutor();
    Date date = new Date();
    System.out.println("Submitting callable task " + date);
    // submitting callable task
    Future<String> future = executor.submit(()->{
      TimeUnit.SECONDS.sleep(4);
      return "Value returned from Callable";
    });
    System.out.println("Submitted callable task " + new Date());
    // getting result 
    try {
      System.out.println("Returned value-" + future.get() + " at " + new Date());
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    executor.shutdown();
  }
}
Output
Submitting callable task Tue Dec 04 11:18:05 IST 2018
Submitted callable task Tue Dec 04 11:18:05 IST 2018
Returned value-Value returned from Callable at Tue Dec 04 11:18:09 IST 2018

As you can see the callable task is submitted for execution to execute in its own thread and the main thread resumes its execution (second System.out is executed immediately after callable submission).

Then the get method is called to retrieve the result of the computation, since get() is a blocking call so it waits for the computation to complete if required.

Future in Java

Future represents the result of an asynchronous computation.

Future interface provides methods to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation.

  • cancel(bollean interruptFlag)- Attempts to cancel execution of this task.
  • get()- Waits if necessary for the computation to complete, and then retrieves its result.
  • get(long timeout, TimeUnit unit)- Waits if necessary for at most the given time for the computation to complete, and then retrieves its result, if available.
  • isCancelled()- Returns true if this task was cancelled before it completed normally.
  • isDone()- Returns true if this task completed.

Callable and Future example

Here is an example of callable and future where 4 callable tasks are executed using the pool of two threads.

public class CallableDemo {
  public static void main(String[] args) {
    // Pool of 2 threads
    ExecutorService executor = Executors.newFixedThreadPool(2);
    System.out.println("Submitting callable tasks " + new Date());
    Future<String> f1 = executor.submit(new MyCallable("Callable task-1"));
    Future<String> f2 = executor.submit(new MyCallable("Callable task-2"));
    Future<String> f3 = executor.submit(new MyCallable("Callable task-3"));
    Future<String> f4 = executor.submit(new MyCallable("Callable task-4"));
    System.out.println("Submitted callable task " + new Date());
                
    // getting result 
    try {
      // Calling get() method to get the future value
      System.out.println("Value for task-1 " + f1.get() + " at " + new Date());
      System.out.println("Value for task-2 " + f2.get() + " at " + new Date());
      while(!f3.isDone()) {
        System.out.println("Waiting for task-3 to complete " + f2.get());
        TimeUnit.MILLISECONDS.sleep(500);
      }
      System.out.println("Value for task-3 after it is completed " + f3.get() + " at " + new Date());
      System.out.println("Value for task-4 " + f4.get() + " at " + new Date());
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
      executor.shutdown();
  }
}

class MyCallable implements Callable<String> {
  String str;
  MyCallable(String str){
    this.str = str;
  }
  @Override
  public String call() throws Exception {
    System.out.println("In call method, thread name- " + Thread.currentThread().getName());
    TimeUnit.SECONDS.sleep(2);
    return str;
  }
}
Output
Submitting callable tasks Tue Dec 04 11:47:23 IST 2018
Submitted callable task Tue Dec 04 11:47:23 IST 2018
In call method, thread name- pool-1-thread-1
In call method, thread name- pool-1-thread-2
In call method, thread name- pool-1-thread-2
In call method, thread name- pool-1-thread-1
Value for task-1 Callable task-1 at Tue Dec 04 11:47:25 IST 2018
Value for task-2 Callable task-2 at Tue Dec 04 11:47:25 IST 2018
Waiting for task-3 to complete Callable task-2
Waiting for task-3 to complete Callable task-2
Waiting for task-3 to complete Callable task-2
Waiting for task-3 to complete Callable task-2
Value for task-3 after it is completed Callable task-3 at Tue Dec 04 11:47:27 IST 2018
Value for task-4 Callable task-4 at Tue Dec 04 11:47:27 IST 2018

As you can see from the output two callable tasks are executed by one thread and two tasks are executed by another thread from the thread pool. In the example isDone() method is also used to check if the submitted task is completed or not.

That's all for the topic Java Callable And Future With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

Installing Java in Windows

This post shows how to install Java in Windows 10. Steps for installing Java in Windows are as follows.

  1. Downloading the latest version of Java.
  2. Installing Java by using the downloaded JDK installer.
  3. Setting the PATH Environment Variable

Downloading Java

You need to download the JDK installer from this location- http://www.oracle.com/technetwork/java/javase/downloads/index.html

Latest version of Java would be at the top which happens to be Java SE 10.0.2 at the time of writing, by scrolling down you can see the other versions of JDK too.

Installing Java Windows

Click the download button below JDK.

You can download JRE if you just want to run Java applications on your system but JDK contains many other tools helpful for development. As per Oracle site this is the description.

  • Software Developers: JDK (Java SE Development Kit). For Java Developers. Includes a complete JRE plus tools for developing, debugging, and monitoring Java applications.
  • End user running Java on a desktop: JRE:(Java Runtime Environment). Covers most end-users needs. Contains everything required to run Java applications on your system.

Once you click the download button you would be taken to the page where you need to accept license agreement and download the java exe file as per your requirement. Note that from Java 9 on wards only 64 bit JDK download is available, till Java 8 there was choice of both 32 bit and 64 bit.

Installing Java using JDK installer in Windows

Once you have the exe file downloaded you can run it by double clicking it that will start the JDK installer. Just follow the instructions provided by the Installation wizard.

Setting the PATH Environment Variable

It is useful to set the PATH variable permanently for Java so that it is persistent after the system is rebooted. Otherwise you will have to give the full path every time you run a program.

To set the PATH variable permanently you need to add the path to jdk-10\bin directory in your Java installation to the PATH variable. Typically the full path would be similar to as follows-

C:\Program Files\Java\jdk-10.0.1\bin 

To set the PATH variable in Windows 10, right click on “This PC” and select Properties. Alternatively you go to Control Panel – System to open the same screen.
Click on Advanced System Settings – Advanced – Environment Variables

There you need to add the location of the bin folder of the JDK installation to the Path variable in System Variables.

For that select path and click Edit and add the path to bin directory in your Java installation- C:\Program Files\Java\jdk-10.0.1\bin

Note that Java 9 onwards JAVA_HOME variable is not needed. If you are installing any older version you also need to add JAVA_HOME variable. Under system variables click New. In the Variable Name field enter “JAVA_HOME” and as value enter the JDK installation path – C:\Program Files\Java\jdk-10.0.1

Want to write your first Java program after installing Java, have a look at this post- Writing First Java Program – Hello World

That’s all for the topic Installing Java in Windows. If something is missing or you have something to share about the topic please write a comment.


You may also like