[Java] Catch Thread Exception

Java has a annoying feature that if any Exception happens, you must report it as throws XXXException.

If you want to run something in a Thread, but still want to catch Exception outside that Thread.

1
2
3
4
5
6
7
8
9
10
    ExecutorService executor = Executors.newCachedThreadPool();
    try {
        executor.execute(new Runnable() {
            public void run () {
                // code might throw Throwable or any other Exceptions.
            }
        });
    } catch (Throwable e) {
            // handling exception here.
    }

Even you use ExecutorService, the compiler still complain that Exception not caught, because Runnable.run() does not declare with throws statement.

1
error: unreported exception Throwable; must be caught or declared to be thrown

Workaround

1. Wrap the exception in RuntimeException

Although Runnable.run() does not allow throws Exception, RuntimeException is still allowed.

Note that we use Exception Chaining in line 8 : .initCause(e) to keep the original Exception message.

1
2
3
4
5
6
7
8
9
10
11
12
    public class XxxThread implements Runnable {
        @Override
        public void run() {
            try {
       ...
            } catch (Throwable e) {
                RuntimeException exp = new RuntimeException();
                exp.initCause(e);
                throw exp;
            }
        }
    }
  • Pro: can catch any Exception, even Throwable object
  • Con: determining which kind of Exception might need more effort, use Throwable.setCause().

2. Use Callable<Type>

Note that Callable.call() can throw Exception.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    final Callable<Integer> callable = new Callable<Integer>() {

        @Override
        public Integer call() throws Exception {
            ... code that can throw a checked exception ...
        }
    };
    final ExecutorService executor = Executors.newSingleThreadExecutor();
    final Future<Integer> future = executor.submit(callable);
    try {
        future.get();  // Exception might happen.
    } finally {
        executor.shutdown();
    }

If any Exception happens, it will throw once we call Future.get(), for more refer to (this)[http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#get()].

  • Pro: can throws Exception as usual.
  • Con:
    • it's a little wired if you have no intend to return anything.
    • .call() can NOT throw Throwable

Reference:

http://stackoverflow.com/questions/6548794/how-do-i-declare-an-exception-in-an-anonymous-thread

留言