Sentry Answers>Java>

Resolving 'java.util.concurrent.TimeoutException' Errors in Java

Resolving 'java.util.concurrent.TimeoutException' Errors in Java

Abdul D.

The Problem

In Java, you may run into a java.util.concurrent.TimeoutException error when using the java.util.concurrent package:

Click to Copy
Task timed out: null java.util.concurrent.TimeoutException at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:204) at TimeoutExceptionExample.main(TimeoutExceptionExample.java:17)

The Solution

You can resolve a java.util.concurrent.TimeoutException error by ensuring the task causing the error does not exceed its timeout limit or by returning a default value when the limit is reached.

The TimeoutException indicates that the error was thrown by the get method of FutureTask. Specifically, it was thrown by the overloaded version of the get method that accepts a timeout parameter, as shown in the following line from the stack trace:

Click to Copy
at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:204)

This design ensures that the task can be controlled and prevented from blocking indefinitely. However, if the specified timeout is too short or the task encounters delays, a TimeoutException error occurs.

Let’s use the following example to reproduce and resolve the issue:

Click to Copy
import java.util.concurrent.*; public class TimeoutExceptionExample { public static void main(String[] args) { ExecutorService executorService = Executors.newSingleThreadExecutor(); Future<Integer> future = executorService.submit(() -> { int sum = 0; for (int i = 1; i <= 1000; i++) { // Add numbers from 1 to 1000 Thread.sleep(1); // Simulate a delay for each addition sum += i; } return sum; }); try { Integer result = future.get(1, TimeUnit.SECONDS); System.out.println("Sum: " + result); } catch (TimeoutException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { executorService.shutdown(); } } }

This code calculates the sum of numbers from 1 to 1000. It simulates a delay for each addition, which causes the task to exceed the timeout limit.

Optimize the Task

First things first: Get rid of any inefficiencies.

The delay in the loop (Thread.sleep(1)) causes the task to take longer than expected. Remove the delay to optimize the code:

Click to Copy
import java.util.concurrent.*; public class OptimizedTimeoutExample { public static void main(String[] args) { ExecutorService executorService = Executors.newSingleThreadExecutor(); Future<Integer> future = executorService.submit(() -> { int sum = 0; for (int i = 1; i <= 1000; i++) { sum += i; // Perform addition without delay. } return sum; }); try { Integer result = future.get(1, TimeUnit.SECONDS); System.out.println("Sum: " + result); } catch (TimeoutException e) { System.err.println("Task timed out: " + e.getMessage()); e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { executorService.shutdown(); } } }

This prints:

Click to Copy
Sum: 500500

Increase the Timeout

When optimization isn’t an option, give the task more time to complete:

Click to Copy
import java.util.concurrent.*; public class TimeoutExceptionExample { public static void main(String[] args) { ExecutorService executorService = Executors.newSingleThreadExecutor(); Future<Integer> future = executorService.submit(() -> { int sum = 0; for (int i = 1; i <= 1000; i++) { sum += i; Thread.sleep(1); } return sum; }); try { Integer result = future.get(3, TimeUnit.SECONDS); // Extend the timeout limit to 3 seconds System.out.println("Sum: " + result); } catch (TimeoutException e) { System.err.println("Task timed out: " + e.getMessage()); e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { executorService.shutdown(); } } }

This prints:

Click to Copy
Sum: 500500

Handle the Timeout Gracefully

If extending the timeout still doesn’t work, you can use a fallback mechanism to handle the error.

This example returns a default value when the task times out:

Click to Copy
import java.util.concurrent.*; public class FallbackTimeoutExample { public static void main(String[] args) { ExecutorService executorService = Executors.newSingleThreadExecutor(); Future<Integer> future = executorService.submit(() -> { int sum = 0; for (int i = 1; i <= 1000000; i++) { try { Thread.sleep(1); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } sum += i; } return sum; }); try { Integer result = future.get(1, TimeUnit.SECONDS); System.out.println("Sum: " + result); } catch (TimeoutException e) { System.err.println("Task timed out. Returning default value."); System.out.println("Sum: 0 (Default value)"); } catch (Exception e) { e.printStackTrace(); } finally { executorService.shutdown(); } } }

This prints:

Click to Copy
Fallback: Task timed out. Returning default value. Sum: 0 (Default value)

Use Asynchronous Processing for the Timeout

Let’s get fancy and use the CompletableFuture method to define a default value in case of a timeout:

Click to Copy
import java.util.concurrent.*; public class CompletableFutureExample { public static void main(String[] args) { // This runs the task asynchronously. CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> { int sum = 0; for (int i = 1; i <= 1000000; i++) { sum += i; try { Thread.sleep(1); // Simulate a delay } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } return sum; }); // If the task does not complete within 1 second, return the default value 1784293664. Integer result = future.completeOnTimeout(1784293664, 1, TimeUnit.SECONDS).join(); System.out.println("Sum: " + result); } }

This prints:

Click to Copy
Sum: 1784293664

Note

The Future interface provides two versions of the get method:

  • get() waits indefinitely for the task to complete.
  • get(long timeout, TimeUnit unit) waits up to the specified timeout for the task to complete, throwing a TimeoutException if the timeout is exceeded.

While using the parameterless get() avoids the TimeoutException` error, it can result in the program waiting indefinitely, which is not ideal.

Further Reading

  • Sentry BlogException Handling in Java (with Real Examples)
  • Syntax.fmListen to the Syntax Podcast
  • Syntax.fm logo
    Listen to the Syntax Podcast

    Tasty treats for web developers brought to you by Sentry. Get tips and tricks from Wes Bos and Scott Tolinski.

    SEE EPISODES

Considered “not bad” by 4 million developers and more than 100,000 organizations worldwide, Sentry provides code-level observability to many of the world’s best-known companies like Disney, Peloton, Cloudflare, Eventbrite, Slack, Supercell, and Rockstar Games. Each month we process billions of exceptions from the most popular products on the internet.

© 2025 • Sentry is a registered Trademark of Functional Software, Inc.