Why am I unable to see the stack trace in Eclipse's console when an unchecked Exception is thrown from a thread different from the main thread?
For example:
ScheduledThreadPoolExecutor scheduledExecutor;
scheduledExecutor.scheduleAtFixedRate(new Log(), 0, LOGGING_FREQUENCY_MS, TimeUnit.MILLISECONDS);
public class Log implements Runnable {
public void run() {
//NullPointerException is thrown
}
}
I get no output. But if I do:
ScheduledThreadPoolExecutor scheduledExecutor;
scheduledExecutor.scheduleAtFixedRate(new Log(), 0, LOGGING_FREQUENCY_MS, TimeUnit.MILLISECONDS);
public class Log implements Runnable {
public void run() {
try {
//NullPointerException is thrown
}catch(Exception e){
e.printStackTrace();
}
}
}
I can see the stack trace.
Why?
EDIT: Follow-up question: What would be the easiest way to print the exceptions thrown by thread-pool threads? Adding try-catch to every single Runnable is of course really ugly.
Why am I unable to see the stack trace in Eclipse's console when an unchecked Exception is thrown from a thread different from the main thread?
Because it is unchecked. By default there is nothing that prints the exceptions thrown by thread-pool threads.
If you want to see the exception then you need to do something like:
Future future = scheduledExecutor.submit(...);
...
try {
// wait for the run() method to finish normally or with a throw
future.get();
} catch (ExecutionException e) {
// the cause of this exception is the one that is thrown by the run()
Throwable cause = e.getCause();
cause.printStackTrace();
}
EDIT: Follow-up question: What would be the easiest way to print the exceptions thrown by thread-pool threads? Adding try-catch to every single Runnable is of course really ugly.
You don't need to add the try/catch to the Runnable
, you add it to the guy who starts the pool.
Another solution would be to write a little RunnableWrapper
which prints out exceptions:
public void RunnableWrapper implements Runnable {
private Runnable delegate;
public RunnableWrapper(Runnable delegate) {
this.delegate = delegate;
}
public void run() {
try {
delegate.run();
} catch (Throwable t) {
t.printStackTrace();
}
}
}
Then you can do:
scheduledExecutor.submit(new RunnableWrapper(myTask));
But the future.get();
is the typical way of solving this.
Because the Executor has "swallowed" the exception. You can see if you got one by querying the returned future:
Future<?> f = scheduledExecutor.scheduleAtFixedRate(new Log(),...);
try {
f.get();
} catch (ExecutionException e) {
Throwable actualException = e.getCause();
}
Note that f.get()
will block until the task is cancelled or throws an exception so you will probably want to call it in a separate thread.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.