Handling Exceptions for ThreadPoolExecutor
When you submit a task to the executor, it returns you a FutureTask
instance.
FutureTask.get()
will re-throw any exception thrown by the task as an ExecutorException
.
So when you iterate through the List<Future>
and call get on each, catch ExecutorException
and invoke an orderly shutdown.
Since you are submitting tasks to ThreadPoolExecutor
, the exceptions are getting swallowed by FutureTask
.
Have a look at this code
**Inside FutureTask$Sync**void innerRun() { if (!compareAndSetState(READY, RUNNING)) return; runner = Thread.currentThread(); if (getState() == RUNNING) { // recheck after setting thread V result; try { result = callable.call(); } catch (Throwable ex) { setException(ex); return; } set(result); } else { releaseShared(0); // cancel }
}
protected void setException(Throwable t) { sync.innerSetException(t);}
From above code, it is clear that setException
method catching Throwable
. Due to this reason, FutureTask
is swallowing all exceptions if you use "submit()
" method on ThreadPoolExecutor
As per java documentation, you can extend afterExecute()
method in ThreadPoolExecutor
protected void afterExecute(Runnable r, Throwable t)
Sample code as per documentation:
class ExtendedExecutor extends ThreadPoolExecutor { // ... protected void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); if (t == null && r instanceof Future<?>) { try { Object result = ((Future<?>) r).get(); } catch (CancellationException ce) { t = ce; } catch (ExecutionException ee) { t = ee.getCause(); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); // ignore/reset } } if (t != null) System.out.println(t); } }
You can catch Exceptions
in three ways
Future.get()
as suggested in accepted answer- wrap entire
run()
orcall()
method intry{}catch{}Exceptoion{}
blocks - override
afterExecute
ofThreadPoolExecutor
method as shown above
To gracefully interrupt other Threads, have a look at below SE question:
How to stop next thread from running in a ScheduledThreadPoolExecutor
Subclass ThreadPoolExecutor
and override its protected afterExecute (Runnable r, Throwable t)
method.
If you're creating a thread pool via the java.util.concurrent.Executors
convenience class (which you're not), take at look at its source to see how it's invoking ThreadPoolExecutor.