[转载]ScheduledThreadPoolExecutor and exception handling

1. Original Question: https://forums.oracle.com/forums/thread.jspa?threadID=1142455

Hi All,
i'm using ScheduledThreadPoolExecutor (with jdk 1.5) and I'm
wondering about exception handling. My first goal is to handle the exceptions
thrown by my Runnable task during its executions. I tried doing my ThreadFactory
in order to add an Thread.UncaughtExceptionHandler to all created threads. This
doesn't work because the exception is always caught by the FutureTask (see
FutureTask$Sync.innerRun()) so my handler is never called.

I tried doing
my Executor:

 1 public class MyExecutor extends ScheduledThreadPoolExecutor {
 2  
 3     private Thread.UncaughtExceptionHandler exceptionHandler = null;
 4  
 5     MyExecutor (int maxThreadPoolSize,
 6                             Thread.UncaughtExceptionHandler exceptionHandler) {
 7         super(maxThreadPoolSize);
 8         this.exceptionHandler = exceptionHandler;
 9     }
10  
11     MyExecutor (int maxThreadPoolSize,
12                             ThreadFactory threadFactory,
13                             Thread.UncaughtExceptionHandler exceptionHandler) {
14         super(maxThreadPoolSize, threadFactory);
15         this.exceptionHandler = exceptionHandler;
16     }
17  
18     @Override
19     protected void afterExecute(Runnable r, Throwable t) {
20         super.afterExecute(r, t);
21         if (r instanceof Future<?>) {
22             try {
23                 if (((Future<?>) r).isDone()) {
24                     Object result = ((Future<?>) r).get();
25                 }
26             } catch (InterruptedException ie) {
27             } catch (ExecutionException ee) {
28                 Throwable realThrowable = ee.getCause();
29                 MyException e = new MyException (realThrowable);
30                 exceptionHandler.uncaughtException(Thread.currentThread(), e);
31             } catch (CancellationException ce) {
32             }
33         }
34     }
35 }

and it seems to work fine.
What do you think about that ?
Done this, my second goal is to re-schedule a task that threw an exception.

Has anyone has an idea ?
A thing I could do is to re-schedule the task in my exception handling, but in that method I don't have any reference to my Runnable object; I have just a ScheduledFuture but I didn't find a way to get my Runnable object and I need a reference to my object because I have different objects run and without that infomation I don't know what to re-schedule.
Can any body shed light on it?
Thanks a lot Stefano

Re: ScheduledThreadPoolExecutor and exception handling

There is always an issue with granularity when it comes to uncaught exceptions.
The UncaughtExceptionHandler acts at the Thread-level such that if the Thread's
run() method terminates due to an exception then the UEH is called. However
there is no mechanism for dealing with uncaught exceptions at the level of
Runnable's. As you discovered FutureTask never lets exceptions escape so the UEH
never comes into play.

One way to deal with it is as you have by
subclassing ScheduledThreadPoolExecutor and using afterExecute to see if you
have a Future and call Future.get which will throw the exception. It is a bit
kludgy to force the exception to be thrown and immediately catch it but you
don't have a choice.

The other option is use a concrete Runnable class
that encapsulates the real Runnable so that it catches all exceptions - that way
the FutureTask never gets them. I prefer this way if you can control submission
to the executor. This way also allows you to re-submit to the executor more
easily - otherwise you have to maintain the association between Runnables and
FutureTasks yourself.

2. Original Question: http://stackoverflow.com/questions/3875739/exception-handling-in-threadpools/3875784#3875784

Solution 1:

Decorator pattern, for example:

 1 public class CatcherRunnable implements Runnable {
 2     private Runnable runMe;
 3 
 4     public CatcherRunnable(Runnable runMe) {
 5         this.runMe = runMe;
 6     }
 7 
 8     public void run() {
 9         try {
10             runMe.run();
11         } catch (Exception ex){
12             ex.printStackTrace();
13         }
14     }
15 }

Wrap all your Runnables with this CatcherRunnable.

 

Solution2: (doesn't work with ScheduledThreadPoolExecutor)

Provide this factory to the Executor you use.

 1 private static class ExceptionCatchingThreadFactory implements ThreadFactory {
 2     private final ThreadFactory delegate;
 3 
 4     private ExceptionCatchingThreadFactory(ThreadFactory delegate) {
 5         this.delegate = delegate;
 6     }
 7 
 8     public Thread newThread(final Runnable r) {
 9         Thread t = delegate.newThread(r);
10         t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
11             @Override
12             public void uncaughtException(Thread t, Throwable e) {
13                 e.printStackTrace();  //replace with your handling logic.
14             }
15         });
16         return t;
17     }
18 }

 

 

posted @ 2013-04-21 20:13  rldts  阅读(491)  评论(0编辑  收藏  举报