Tag Archives: concurrent

Guava: Using CheckedFuture

In this post, I want to discuss another class from Google Guava. Today, it will be CheckedFuture. Let’s first see the JavaDoc of the class:

A CheckedFuture is an extension of Future that includes versions of the get methods that can throw a checked exception and allows listeners to be attached to the future. This makes it easier to create a future that executes logic which can throw an exception.

Implementations of this interface must adapt the exceptions thrown by Future#get(): CancellationException, ExecutionException and InterruptedException into the type specified by the E type parameter.

This interface also extends the ListenableFuture interface to allow listeners to be added. This allows the future to be used as a normal Future or as an asynchronous callback mechanism as needed. This allows multiple callbacks to be registered for a particular task, and the future will guarantee execution of all listeners when the task completes.

From this explanation, we can conclude two things about CheckedFuture:

  1. It extends ListenableFuture which has been discussed in this article.
  2. It aims to simplify exception management of Future.

Let’s look at code. Normally, if Future execution is cancelled because the inner-process throws exception, it will wrap the exception in a ExecutionException. So, our code will looks like something like this.

try {
	task.get();
} catch (ExecutionException e) {
	if (e.getCause()
			instanceof ApplicationException) {
		throw (ApplicationException) e.getCause();
	}
	throw new ApplicationException(e);
} catch (InterruptedException e) {
	throw new ApplicationException(e);
} catch (CancellationException e) {
	throw new ApplicationException(e);
}

A lazy programmer (don’t we all are lazy)? will write that like this:

try {
	task.get();
} catch (Exception e) {
	if (e.getCause()
			instanceof ApplicationException) {
		throw (ApplicationException) e.getCause();
	}
	throw new ApplicationException(e);
}

The same code can be implemented using CheckedFuture like this:

Function<Exception, ApplicationException> mapper =
	new Function<Exception, ApplicationException>() {

	@Override
	public ApplicationException apply(
			Exception from) {
		if (from.getCause() instanceof ApplicationException) {
			throw (ApplicationException) from.getCause();
		}
		throw new ApplicationException(from);
	}
};
CheckedFuture<String, ApplicationException> checkedTask =
	Futures.makeChecked(task, mapper);

checkedTask.checkedGet();

So I guess you’ll say: ‘but the code is longer than the original’. It’s true that in this example the code seems to be longer. In fact, if your case is so simple like this, I’ll suggest you to just use the original version.

This is pretty much same case of using functional-like Java coding style. It’s overkill if the case is so small. The advantage can only be seen once your code grows bigger.

In this CheckedFuture case, one example where using it will give you huge benefit is when you start sending the Future/CheckedFuture around and the get()/checkedGet() is executed in many places. That time, you’ll see that wrapping each call will try catch is annoying and this is where CheckedFuture-based solution will shine.

Guava: Using ListenableFuture

Google Guava has many interesting classes which we can use on our application. The ones from collection package have been already used by many developers and this blog has tutorial on how to use the computing map.

I want to move to the other package. This one is com.google.common.util.concurrent, specifically I want to introduce ListenableFuture. The documentation of the class is as follow:

This interface defines a future that has listeners attached to it, which is useful for asynchronous workflows. Each listener has an associated executor, and is invoked using this executor once the Future’s computation is Future#isDone() complete}. The listener will be executed even if it is added after the computation is complete.

Consider following example. If we have task T1, T2, and T3. T2 can only be done when T1 is finished and T3 can only be done once T2 is ended. The diagram below shows the dependency.

The easiest solution without any concurrency is of course to just run each task one after another. But consider that we have 5 set of these operation. Without thread we can end up with serial solution depicted by the following picture.

ListenableFuture made it easy to create the concurrent version of the solution.

This is a code example of this solution which will print “1”, then pause for a second before printing “2”, and another stop for 1 second before finally printing “3”. Note that ListenableFutureTask extends ListenableFuture.

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.google.common.util.concurrent.ListenableFutureTask;

public class TestListenableFuture {

	static class SimpleTask extends
			ListenableFutureTask<Void> {
		SimpleTask(final String message) {
			super(new Callable<Void>() {

				@Override
				public Void call() throws Exception {
					System.out.println(message);
					Thread.sleep(1000);
					return null;
				}
			});
		}
	}

	public static void main(String[] args) {
		ListenableFutureTask<Void> task1 =
			new SimpleTask("1");
		ListenableFutureTask<Void> task2 =
			new SimpleTask("2");
		ListenableFutureTask<Void> task3 =
			new SimpleTask("3");

		ExecutorService exec =
			Executors.newSingleThreadExecutor();
		exec.submit(task1);
		task1.addListener(task2, exec);
		task2.addListener(task3, exec);

		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
		}
		exec.shutdown();
	}
}

Pretty easy, isn’t it? And we can probably extend this solution to create a full workflow framework solution.

UPDATE: Remember that the API is still in Beta version. I’ll try to update it once the release version is released