What is the best approach for handling exceptions thrown in a separate thread?

I am working on a J2ME project that creates workflows to perform numerous tasks, such as loading HTTP content. The basic layout of threads is similar to most java applications - there is a main user interface thread and workflows created to work behind the scenes. My question is the best way to handle exceptions thrown in workflows?

I usually adhere to the rationale that most exceptions should be percolated as much as possible. When I write single-threaded applications, it is common for me to overflow exceptions up to the user interface level, and then report them to the user in the error dialog box. Is there a similar practice for multithreaded applications? The most intuitive thing for me is to catch the exceptions in Thread.run () and then call invokeLater in the user interface thread to report this in the dialog box. The problem I see here is that outside of the workflow that prematurely dies, this approach does not really notify the user interface thread, an error has occurred. I donโ€™t see a clear way to throw an exception on threads, so to speak.

Thanks Andy

+4
source share
2 answers

You do not have to hammer the user code in your workers!

/** * TWO CHOICES: * - Monitor your threads and report errors, * - setup a callback to do something. */ public class ThreadExceptions { /** Demo of {@link RunnableCatch} */ public static void main(String[] argv) throws InterruptedException { final Runnable bad = new NaughtyThread(); // safe1 doesnt have a callback final RunnableCatch safe1 = new RunnableCatch(bad); // safe2 DOES have a callback final RunnableCatch safe2 = new RunnableCatch(bad, new RunnableCallback() { public void handleException(Runnable runnable, Exception exception) { System.out.println("Callback handled: " + exception.getMessage()); exception.printStackTrace(); } }); final Thread t1 = new Thread(safe1, "myThread"); final Thread t2 = new Thread(safe2, "myThread"); t1.start(); t2.start(); t1.join(); t2.join(); if (safe1.getException() != null) { System.out.println("thread finished with exceptions"); safe1.getException().printStackTrace(); } System.out.println("done"); } } /** Throws an exception 50% of the time */ class NaughtyThread implements Runnable { public void run() { try { if (Math.random() > .5) { throw new RuntimeException("badness"); } } finally { System.out.println("ran"); } } } /** Called when an exception occurs */ interface RunnableCallback { void handleException(Runnable runnable, Exception exception); } /** * Catches exceptions thrown by a Runnable, * so you can check/view them later and/or * deal with them from some callback. */ class RunnableCatch implements Runnable { /** Proxy we will run */ private final Runnable _proxy; /** Callback, if any */ private final RunnableCallback _callback; /** @guarded-by(this) */ private Exception _exception; public RunnableCatch(final Runnable proxy) { this(proxy, null); } public RunnableCatch(final Runnable proxy, RunnableCallback target) { _proxy = proxy; _callback = target; } public void run() { try { _proxy.run(); } catch (Exception e) { synchronized (this) { _exception = e; } if (_callback != null) { _callback.handleException(_proxy, e); } } } /** @return any exception that occured, or NULL */ public synchronized Exception getException() { return _exception; } } 
+7
source

Another parameter other than what Stuph gave is to set exceptions in the local thread. If another exception occurs before this exception is cleared, an assertion will occur. This at least gives someone a chance to spot the exception and handle it.

0
source

All Articles