Explain Codes LogoExplain Codes Logo

How to catch an Exception from a thread

java
exception-handling
threading
concurrency
Anton ShumikhinbyAnton Shumikhin·Jan 22, 2025
TLDR

Keeping a track of exceptions in a thread becomes easier with Thread.UncaughtExceptionHandler. Simply attach it to your thread and see it in action for uncaught runtime exceptions. Look at the example below:

Thread thread = new Thread(() -> { throw new RuntimeException("Thread goes oops!"); }); thread.setUncaughtExceptionHandler((t, e) -> System.out.println("Gotcha: " + e)); thread.start();

This code cleverly catches and prints "Gotcha: java.lang.RuntimeException: Thread goes oops!", ensuring you catch the exceptions effectively on-the-fly.

Methodologies to handle exceptions in threads

Feeling adventurous with multi-threading? Sit tight, because exception handling is here to challenge you. But fear not, just follow these guidelines and technologies to improve the reliability of your multi-threaded applications.

Dealing with callable and future

Callable interface and Future are your friends when managing exceptions in threads:

ExecutorService executorService = Executors.newSingleThreadExecutor(); Future<String> future = executorService.submit(() -> { throw new RuntimeException("It's getting wild in here!"); // Party going wild with exceptions }); try { future.get(); } catch (InterruptedException ie) { // I got interrupted, not fair! } catch (ExecutionException ee) { // Catch the RuntimeException as ExecutionException Throwable cause = ee.getCause(); System.out.println("Caught ya: " + cause); } finally { executorService.shutdown(); }

Note, how Callable and Future have made handling exceptions as easy as pie, almost like dealing with a regular method call inside a try-catch block.

Utilizing universal handler for runaway exceptions

For an excelling catch-all strategy, set the default uncaught exception handler:

Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> { System.out.println("Universal catcher at rescue: " + throwable); // Going all Avengers on exceptions });

This handler is a superhero that comes into action when a thread without its own UncaughtExceptionHandler lets an exception escape the run method.

Exception handling for thread pools

Using ExecutorService to manage a pool of threads, any exceptionally completed task can lead to an ExecutionException while fetching result:

ExecutorService executor = Executors.newFixedThreadPool(10); Future<?> future = executor.submit(yourTask); try { future.get(); } catch (ExecutionException ex) { Throwable cause = ex.getCause(); // Your task threw a tantrum, let's handle it! }

This smart pattern ensures your tasks inside a multi-threaded pool behave well, even when they whine about exceptions.

Enhancing robustness of multi-threaded applications

Thread exceptions can turn your multi-threaded program into a field of landmines. Here are some pro-tips to keep your program standing tall:

Keeping track of thread states

Threads have various states, and exceptions could pop up anywhere. Make sure your exception logging and fallback mechanisms are aligned with this.

Expect concurrency problems

Concurrency can be challenging to manage. Stay ready for race conditions, deadlocks, and exceptions that might come with it. Use synchronization, or higher-level concurrency utilities from java.util.concurrent.

Health check on threads

Long-running threads need a regular health check-up. Maintain procedures to quickly catch exceptions and isolate them from causing further damage to your system.