Callable and Future in Java

Here I am going to give you an example on Callable and Future in Java.

public interface Callable<V>

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>

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.

Callable and Future Example

POJO Class

Create a simple POJO class that will be used for your Callable and Future implementation.

package com.roytuts.java.callable.future;

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 the Callable interface.

package com.roytuts.java.callable.future;

import java.util.concurrent.Callable;

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.java.callable.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;

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();
	}

}

Running the CustomFuture class, you will get below output:

inside call() => Job Id : 01
inside call() => Job Status : In Progress
inside call() => Job Id : 03
inside call() => Job Status : Sent
inside call() => Job Id : 02
returned : Job [id=01, status=In Progress]
inside call() => Job Id : 04
inside call() => Job Status : Complete
inside call() => Job Status : Sending
java.lang.Exception: Runtime Exception
	at com.roytuts.java.callable.future.CustomCallable.call(CustomCallable.java:18)
	at com.roytuts.java.callable.future.CustomCallable.call(CustomCallable.java:1)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:835)
Caused by: java.lang.NullPointerException
	at com.roytuts.java.callable.future.CustomCallable.call(CustomCallable.java:15)
	... 5 more
returned : Job [id=02, status=Sending]
returned : Job [id=03, status=Sent]
returned : Job [id=04, status=Complete]

In the above you are getting NullPointerException because a Callable with null value is submitted to the executor service.

Source Code

Download

Thanks for reading.

Leave a Comment