Handling Exceptions for ThreadPoolExecutor

后端 未结 3 1398
没有蜡笔的小新
没有蜡笔的小新 2020-12-03 03:00

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.

3条回答
  •  眼角桃花
    2020-12-03 03:51

    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

提交回复
热议问题