Reputation: 601
I have an inner class that extends Thread
private class TestStart extends Thread {
public void run() {
try {
startServer();
}
catch (Exception e) {
/// How to handle it?
}
}
}
The caller in the main thread:
public void start() throws Exception {
Thread st = new TestStart();
st.start();
}
Method startServer() throws Exception by its API, so I have to use try-catch as Thread.run() does not "throws" exception in method definition. I need to bubble up the caught exception into the main thread to handle it. Is there an easy way to do it? Thanks
Upvotes: 1
Views: 7100
Reputation: 1587
There is a few possible solutions. For example:
Use setUncaughtExceptionHandler()/setDefaultUncaughtExceptionHandler() and change your try/catch
try {
startServer();
}
catch (RuntimeException e) {
throw e;
}
catch (Exception e) {
throw new RuntimeException(e);
}
Or use your custom listener
private class TestStart extends Thread {
private final ServerStateListener lnr;
TestStart(ServerStateListener lnr) {
this.lnr = lnr;
}
public void run() {
try {
startServer();
lnr.onServerStarted();
}
catch (Exception e) {
lnr.onServerStoppedByError(e);
}
}
}
Or just save Exception and read it after .join
private class TestStart extends Thread {
private Exception error; // if you start and join and read this property within one thread, you don't need to use volatile, otherwise do it for safe publication
public void run() {
try {
startServer();
}
catch (Exception e) {
error = e;
}
}
public Exception getError() {
return error;
}
}
Or use ExecutorService/Callable instead of your own thread as Andy suggested.
Upvotes: 1
Reputation: 140328
If you use an ExecutorService
instead of using raw threads, you can be notified of uncaught exceptions:
class MyCallable implements Callable<Void> {
@Override public Void call() throws Exception {
// Do something - you don't need to catch Exception as Callable throws it.
// ...
return null; // A return is necessary from a Callable.
}
}
Create an executor service somewhere, e.g.:
ExecutorService executor = Executors.newFixedThreadPool(1);
Then, in the code where you start the thread:
Future<?> future = executor.submit(new MyCallable());
try {
future.get(); // Blocks until the Callable completes.
} catch (ExecutionException e) {
// You reach here if an exception is thrown in the Callable -
// The exception is accessible via e.getCause().
}
Upvotes: 4
Reputation: 2954
Set a new exception handler on your Thread.
st.setDefaultUncaughtExceptionHandler(new Thread.
UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
System.out.println(t + " throws exception: " + e);
}
});
And place that code before your start();
Upvotes: 0