Timeout support using ExecutorService and Futures

The other day, I was in need of a way to timeout a third-party service that started to freeze from time to time. After looking around a bit, I ended up using ExecutorService and Future from the concurrent package.

What I liked about this solution was that it made the thread handling quite abstract, leaving me with some clean and understandable code that wouldn’t give anyone any surprises.

So, what do the different parts do?

ExecutorService executes submitted runnable tasks, offering possibilities of termination or to produce a Future.

A Future represents the pending result of an asynchronous computation. It offers a method, called get, that returns the result of the computation when it's done. Additionally it allows us to set a limit of how long we're willing to wait. If the result isn't returned within the limit, the get method will throw a TimeoutException.

Now, let's create an example using this approach.

I’m going to continue with the article theme from last post. Let's say we want to publish a list of articles, but we have some problems with this process. The result of this problem is that this part of the code freezes. We now want to use the approach described above to be able to timeout if this problem occurs.

public List<PublishResult> publishArticles(List<Article> articles) throws InterruptedException, ExecutionException {

    ExecutorService executorService = Executors.newSingleThreadExecutor();

    return articles.stream()
            .map(article -> {

                Future<PublishResult> task = executorService.submit(() -> publisher.publish(article));

                try {
                    return task.get(10, TimeUnit.SECONDS);
                } catch (InterruptedException | ExecutionException | TimeoutException e) {
                    return PublishResult.FAILED(article);

Pretty cool right?

First we create a single-threaded ExecutorService by calling Executors.newSingleThreadExecutor(). This executor guarantees that the tasks will be executed sequentially. It also makes sure to fire up a new thread if the active one dies. It's worth mentioning that the Executors class offers different types of ExecutorServices. Another example of this is newFixedThreadPool() which lets you decide the maximum amount of active threads.

Next we start iterating the list, using the map operation from the stream API, which I went through in an earlier post, to publish each of the articles. This is where the fun is happening, so let’s take a closer look at the function we send into the map operation.

First we submit the task of publishing the article to ExecutorService. The submit method of ExecutorService takes the Callable interface from the concurrent package as an argument. This is a SAM-type interface, which means that we can send the implementation as a lambda expression. However, if you're still stuck on Java 7 or lower, you can just create an anonymous class.

After submitting the task, we get a Future object back. Next we try to get the result from this object using the get method. This method throws a few types of exceptions.

  • InterruptedException - If the current thread was interrupted while waiting.
  • ExecutionException - If the computation threw an exception.
  • TimeoutException - If the computation didn’t complete within our time limit.

For simplicity, I’ve combined them in one catch, but the TimeoutException is what we’re after in this post. If the exception occurs, we return a failed result.

Now, let’s check if this approach works, by creating a few tests.

Let’s start with a test making the publish method throw a TimeoutException.

public void testPublisherTimeout() throws Exception {

    PublishArticlesUseCase useCase = new PublishArticlesUseCase(article -> {
        return PublishResult.OK(article);

    List<Article> articles = Arrays.asList(new Article(3, "Java rises again"));
    List<PublishResult> result = useCase.publishArticles(articles);

    assertEquals(result.get(0).getStatus(), PublishResult.Status.FAILED);

Next, a test that successfully publishes the article.

public void testPublisherOk() throws Exception {

    PublishArticlesUseCase useCase = new PublishArticlesUseCase(article -> PublishResult.OK(article));

    List<Article> articles = Arrays.asList(new Article(3, "Java rises again"));
    List<PublishResult> result = useCase.publishArticles(articles);

    assertEquals(result.get(0).getStatus(), PublishResult.Status.OK);

You can find the source code of the examples above here.

Enjoyed the post?

If you don't want to miss future posts, make sure to subscribe