I have the following code snippet that basically scans through the list of task that needs to be executed and each task is then given to the executor for execution.
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.
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 answerrun()
or call()
method in try{}catch{}Exceptoion{}
blocksafterExecute
of ThreadPoolExecutor
method as shown aboveTo gracefully interrupt other Threads, have a look at below SE question:
How to stop next thread from running in a ScheduledThreadPoolExecutor
How to forcefully shutdown java ExecutorService
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.