Future And Callable

Callable is a function that will be executed asynchronously that can be used to submit to a Thread

Future is the result of this asynchronous function

Callable

Can be used to create a function to be call.

For example, we have

public static void main(String[] args) {
	try {
		Integer result = myCallableFunction().call();
		System.out.println("result: " + result);
	} catch (Exception e) {
		throw new RuntimeException(e);
	}
}

public static Callable<Integer> myCallableFunction() {
	return () -> {
		System.out.printf("%s working on this%n", Thread.currentThread().getName());
		Thread.sleep(5000);
		System.out.printf("%s finished on this%n", Thread.currentThread().getName());
		return 5;
	};
}

As a result we have

main working on this
main finished on this
result: 5

[!note]
This is still being executed synchronously

Future

To have a Future we need to make our Callable to be executed asynchronously.

CompletableFuture

One way is to use the CompletableFuture that will use a thread in java Common Pool

public static void main(String[] args) {  
	Future<Integer> result = myCallableFunction();
	System.out.println("Some code executed in between");
	try {
		System.out.println("result: " + result.get());
	} catch (InterruptedException | ExecutionException e) {
		throw new RuntimeException(e);
	}
}

public static CompletableFuture<Integer> myCallableFunction() {
	return CompletableFuture.supplyAsync(() -> {
		System.out.printf("%s working on this%n", Thread.currentThread().getName());
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			throw new RuntimeException(e);
		}
		System.out.printf("%s finished on this%n", Thread.currentThread().getName());
		return 5;
	});
}

In here, the callable function is wrapped with CompletableFuture.supplyAsync as a Supplier. As a result, this function will be executed on its own thread.

As a result, we have the following:

Some code executed in between
ForkJoinPool.commonPool-worker-1 working on this
ForkJoinPool.commonPool-worker-1 finished on this
result: 5

[!note]
Note that Callable does not work with CompletableFuture.supplyAsync directly. In the example above, we used the same code in Callable as the Supplier inside supplyAsync. However, Callable does work with ExecutorService directly

ExecutorService

ExecutorService works with Callable directly. The submit() function takes in a Callable and returns a Future.

<T> Future<T> submit(Callable<T> task);

For example:

public static void main(String[] args) {
	ExecutorService executorService = Executors.newCachedThreadPool();
	Future<?> result = executorService.submit(() -> process());
	executorService.shutdown();

	try {
		System.out.println("result: " + result.get());
	} catch (InterruptedException | ExecutionException e) {
		throw new RuntimeException(e);
	}
}

public static int process() {
	int random = (new Random()).nextInt(5000);
	System.out.printf("%s working on this for %s%n" , Thread.currentThread().getName(), random);
	try {
		Thread.sleep(random);
	} catch (InterruptedException exception) {
		exception.printStackTrace();
	}

	return random;
}

[!note]
When we call result.get() in both scenario of CompletableFuture.supplyAsync or ExecutorService, the thread block indefinitely until it gets the result.

As a result, we have the following logs:

pool-1-thread-1 working on this for 2447
result: 2447

Note that in here we're not using the Common Pool anymore in contrast to the previous method.