Callable and Future in Java

public interface Callable<V>

http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Callable.html

A task that returns a result and may throw an exception. Implementors define a single method with no arguments called call.

The Callable interface is similar to Runnable, in that both are designed for classes whose instances are potentially executed by another thread. A Runnable, however, does not return a result and cannot throw a checked exception.

The Executors class contains utility methods to convert from other common forms to Callable classes.

public interface Future<V>

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html

A Future represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation. The result can only be retrieved using method get when the computation has completed, blocking if necessary until it is ready. Cancellation is performed by the cancel method. Additional methods are provided to determine if the task completed normally or was cancelled. Once a computation has completed, the computation cannot be cancelled. If you would like to use a Future for the sake of cancellability but not provide a usable result, you can declare types of the form Future<?> and return null as a result of the underlying task.

Example

Create a POJO class

package com.roytuts.pojo;

public class Job {

  private String id;
  private String status;

  public synchronized String getId() {
    return id;
  }

  public synchronized void setId(String id) {
    this.id = id;
  }

  public synchronized String getStatus() {
    return status;
  }

  public synchronized void setStatus(String status) {
    this.status = status;
  }

  @Override
  public String toString() {
    return "Job [id=" + id + ", status=" + status + "]";
  }

}

Create CustomCallable class that implements Callable interface

package com.roytuts.callable;

import java.util.concurrent.Callable;

import com.roytuts.pojo.Job;

public class CustomCallable implements Callable<Job> {

  private Job job;

  public CustomCallable(Job job) {
    this.job = job;
  }

  @Override
  public Job call() throws Exception {
    try {
      System.out.println("inside call() => Job Id : " + job.getId());
      System.out.println("inside call() => Job Status : " + job.getStatus());
    } catch (Exception e) {
      throw new Exception("Runtime Exception", e);
    }
    return job;
  }

}

Create CustomFuture class which submits Jobs to the ExecutorService

package com.roytuts.future;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import com.roytuts.callable.CustomCallable;
import com.roytuts.pojo.Job;

public class CustomFuture {

  public static void main(String[] args) {
    List<Future<Job>> futures = new ArrayList<Future<Job>>();
    ExecutorService taskExecutor = Executors.newFixedThreadPool(5);
    
    Job job1 = new Job();
    job1.setId("01");
    job1.setStatus("In Progress");
    Future<Job> future1 = taskExecutor.submit(new CustomCallable(job1));
    futures.add(future1);

    Future<Job> futureNull = taskExecutor.submit(new CustomCallable(null));
    futures.add(futureNull);

    Job job2 = new Job();
    job2.setId("02");
    job2.setStatus("Sending");
    Future<Job> future2 = taskExecutor.submit(new CustomCallable(job2));
    futures.add(future2);

    Job job3 = new Job();
    job3.setId("03");
    job3.setStatus("Sent");
    Future<Job> future3 = taskExecutor.submit(new CustomCallable(job3));
    futures.add(future3);

    Job job4 = new Job();
    job4.setId("04");
    job4.setStatus("Complete");
    Future<Job> future4 = taskExecutor.submit(new CustomCallable(job4));
    futures.add(future4);

    // After all tasks have started, now wait for all of them to complete (they run in parallel)
    // and check if there were any exceptions

    for (Future<Job> future : futures) {
      try {
        System.out.println("returned : " + future.get().toString());
      } catch (ExecutionException e) {
        e.getCause().printStackTrace();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }

    //shut down the executor service now
    taskExecutor.shutdown();
  }

}

Run the CustomFuture class, you will get below output

inside call() => Job Id : 02
inside call() => Job Id : 03
inside call() => Job Id : 01
inside call() => Job Status : In Progress
inside call() => Job Status : Sending
inside call() => Job Status : Sent
inside call() => Job Id : 04
inside call() => Job Status : Complete
returned : Job [id=01, status=In Progress]
returned : Job [id=02, status=Sending]
returned : Job [id=03, status=Sent]
returned : Job [id=04, status=Complete]
java.lang.Exception: Runtime Exception
	at com.roytuts.callable.CustomCallable.call(CustomCallable.java:21)
	at com.roytuts.callable.CustomCallable.call(CustomCallable.java:1)
	at java.util.concurrent.FutureTask.run(FutureTask.java:262)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException
	at com.roytuts.callable.CustomCallable.call(CustomCallable.java:18)
	... 5 more

Thanks for reading.

Soumitra Roy Sarkar

I am a professional Web developer, Enterprise Application developer, Software Engineer and Blogger. Connect me on Roy Tutorials Twitter Facebook  Google Plus Linkedin Or Email Me

Leave a Reply

Your email address will not be published. Required fields are marked *