HowToDoInJava

  • Python
  • Java
  • Spring Boot
  • Dark Mode
Home / Java / Multi-threading / Callable Future Example

Callable Future Example

Learn to execute callable tasks (which return a result of type Future after execution) using ExecutorService implementations in this simple Callable Future example.

1. Important interfaces

1.1. Callable

In Java concurrency, Callable represents a task that returns a result. Executor 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.

@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;
}

1.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 completed, blocking if necessary until it is ready.

Cancellation of a task is performed by the cancel() method. Once a computation has completed, the computation cannot be cancelled.

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. Callable Future Example

In this example, we are creating a task which will return the factorial of a given number. The return value of the task after it’s completion is the factorial of argument number.

class FactorialCalculator implements Callable<Integer> 
{
	private final Integer number;

	public FactorialCalculator(Integer number) {
		this.number = number;
	}

	@Override
	public Integer call() throws Exception {

		int result = 1;

		if ((number == 0) || (number == 1)) {
			result = 1;
		} else {
			for (int i = 2; i <= number; i++) {
				result *= i;
				TimeUnit.MILLISECONDS.sleep(20);
			}
		}

		System.out.printf("Factorial of %d is :: %d\n", number, result);
		return result;
	}
}

Now when the calculator is ready, we will use ExecutorService to execute the tasks. Here we will create 10 tasks which will compute factorial of numbers 1 to 10.

Each task will be submitted to ExecutorService internally managing thread pool of 2 threads.

We will use method awaitTermination() to wait for all tasks to complete before checking the output of all tasks.It is optional step, and we are allowed not to wait and start checking the outputs as an when a task is complete.

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

public class Main 
{
	public static void main(String[] args) throws InterruptedException 
	{
		ExecutorService executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);

		List<Future<Integer>> resultList = new ArrayList<>();

		for (int i = 1; i <= 10; i++) {
			FactorialCalculator calculator = new FactorialCalculator(i);
			Future<Integer> result = executor.submit(calculator);
			resultList.add(result);
		}
		
		executor.awaitTermination(5, TimeUnit.SECONDS);

		for (int i = 0; i < resultList.size(); i++) 
		{
			Future<Integer> result = resultList.get(i);
			Integer number = null;
			try {
				number = result.get();
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (ExecutionException e) {
				e.printStackTrace();
			}
			System.out.printf("Main: Task %d: %d\n", i, number);
		}

		executor.shutdown();
	}
}

Program output.

Factorial of 1 is :: 1
Factorial of 2 is :: 2
Factorial of 3 is :: 6
Factorial of 4 is :: 24
Factorial of 5 is :: 120
Factorial of 6 is :: 720
Factorial of 7 is :: 5040
Factorial of 8 is :: 40320
Factorial of 9 is :: 362880
Factorial of 10 is :: 3628800

Main: Task 0: 1
Main: Task 1: 2
Main: Task 2: 6
Main: Task 3: 24
Main: Task 4: 120
Main: Task 5: 720
Main: Task 6: 5040
Main: Task 7: 40320
Main: Task 8: 362880
Main: Task 9: 3628800

In above example, when we send callable object to be executed in an executor using the submit() method, it returns a Future object that you can use with two main objectives:

3. Conclusion

Above example demonstrate that –

  • We can control the status of the task i.e. we can cancel the task after checking whether it has finished or not. For this purpose, we can use the isDone() method.
  • We can get the result returned using 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, then the get() method throws an ExecutionException exception as well.

Drop me your questions related to Java ExecutorService Callable Example in comments.

Happy Learning !!

Was this post helpful?

Let us know if you liked the post. That’s the only way we can improve.

Share this:

  • Twitter
  • Facebook
  • LinkedIn
  • Reddit

About Lokesh Gupta

A family guy with fun loving nature. Love computers, programming and solving everyday problems. Find me on Facebook and Twitter.

Comments are closed on this article!

Search Tutorials

Java Concurrency Tutorial

  • Java Concurrency – Introduction
  • Concurrency Evolution
  • Thread Safety
  • Concurrency vs. Parallelism
  • Compare and Swap [CAS]
  • synchronized keyword
  • Object vs. Class Level Locking
  • Runnable vs. Thread
  • wait(), notify() and notifyAll()
  • Yield() vs. Join()
  • Sleep() vs. Wait()
  • Lock vs. Monitor
  • Callable + Future
  • UncaughtExceptionHandler
  • Throttling Task Submission
  • Executor Best Practices
  • Inter-thread Communication
  • Write and Resolve Deadlock

Java Concurrency Utilities

  • AtomicInteger
  • Lock
  • ThreadFactory
  • ThreadLocal
  • ExecutorService
  • ThreadPoolExecutor
  • FixedSizeThreadPoolExecutor
  • ScheduledThreadPoolExecutor
  • Semaphore
  • Binary Semaphore
  • BlockingQueue
  • DelayQueue
  • ConcurrentLinkedDeque
  • CountDownLatch
  • ForkJoinPool

Java Tutorial

  • Java Introduction
  • Java Keywords
  • Java Flow Control
  • Java OOP
  • Java Inner Class
  • Java String
  • Java Enum
  • Java Collections
  • Java ArrayList
  • Java HashMap
  • Java Array
  • Java Sort
  • Java Clone
  • Java Date Time
  • Java Concurrency
  • Java Generics
  • Java Serialization
  • Java Input Output
  • Java New I/O
  • Java Exceptions
  • Java Annotations
  • Java Reflection
  • Java Garbage collection
  • Java JDBC
  • Java Security
  • Java Regex
  • Java Servlets
  • Java XML
  • Java Puzzles
  • Java Examples
  • Java Libraries
  • Java Resources
  • Java 14
  • Java 12
  • Java 11
  • Java 10
  • Java 9
  • Java 8
  • Java 7

Meta Links

  • About Me
  • Contact Us
  • Privacy policy
  • Advertise
  • Guest and Sponsored Posts

Recommended Reading

  • 10 Life Lessons
  • Secure Hash Algorithms
  • How Web Servers work?
  • How Java I/O Works Internally?
  • Best Way to Learn Java
  • Java Best Practices Guide
  • Microservices Tutorial
  • REST API Tutorial
  • How to Start New Blog

Copyright © 2020 · HowToDoInjava.com · All Rights Reserved. | Sitemap

  • Java 15 New Features
  • Sealed Classes and Interfaces
  • EdDSA (Ed25519 / Ed448)