Handling Exceptions for ThreadPoolExecutor

巧了我就是萌 提交于 2019-11-27 20:37:41
matt b

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.

Ravindra babu

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

  1. Future.get() as suggested in accepted answer
  2. wrap entire run() or call() method in try{}catch{}Exceptoion{} blocks
  3. override afterExecute of ThreadPoolExecutor 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

How to forcefully shutdown java ExecutorService

Paul Cameron

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!