Request (bug fix?) for ScheduledThreadPoolExecutor

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Request (bug fix?) for ScheduledThreadPoolExecutor

Norman Elton
If I create a ThreadPoolExecutor that overrides the beforeExecute and  
afterExecute methods, I see my Runnable go into the pool, and come  
out. This is very handy.

If I change to a ScheduledThreadPoolExecutor, the objects passed to  
these methods are of type ScheduledFutureTask, not my original  
objects. Looking at the code, it appears that  
ScheduledThreadPoolExecutor wraps my Runnable inside this new object.

So the question is... Is this necessary? For immediate executions  
(non-scheduled), could the internals of ScheduledThreadPoolExecutor  
keep my Runnables intact, or provide some way to get them back after  
execution?

Thanks for any advice,

Norman Elton

------------------------------------------------------
Norman Elton
Information Technology - Network Engineering
College of William & Mary
757-221-7790



_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Request (bug fix?) for ScheduledThreadPoolExecutor

tpeierls
Norman Elton wrote:

> If I create a ThreadPoolExecutor that overrides the beforeExecute and  
> afterExecute methods, I see my Runnable go into the pool, and come  out.
> This is very handy.
>
> If I change to a ScheduledThreadPoolExecutor, the objects passed to  
> these methods are of type ScheduledFutureTask, not my original  objects.
> Looking at the code, it appears that  ScheduledThreadPoolExecutor wraps
> my Runnable inside this new object.
>
> So the question is... Is this necessary? For immediate executions  
> (non-scheduled), could the internals of ScheduledThreadPoolExecutor  
> keep my Runnables intact, or provide some way to get them back after  
> execution?

TPE works in terms of execute(Runnable); the implementations of
submit(Callable) and STPE.schedule(Runnable,...) wrap the Callable or
scheduled Runnable to provide a return value and/or delayed execution -- this
wrapped task has to be a Runnable so that TPE can execute it.

There is currently no standard way to map back from the wrapper to its
contained Callable or Runnable, so beforeExecute and afterExecute get passed
the wrapper Runnable.

But you can do this mapping yourself, for example, by storing the
ScheduledFuture and associated Runnable in a Map when submitting:

     Map<Object, Runnable> map = ...;
     ScheduledFuture<?> f = ses.schedule(runnable, 100, MILLISECONDS);
     map.put(f, runnable);

Then in beforeExecute/afterExecute, you can look up the "real" Runnable:

     void beforeExecute(Thread t, Runnable r) {
         if (map.containsKey(r))
             r = map.get(r);
         // use r
     }

This is inconvenient, and it relies on a private implementation detail. But
there is hope: JDK 6.0 is slated to provide protected methods that you can
override to control the type of the returned wrapper, at which point this will
all become a bit easier, because you can then use a custom wrapper that
"knows" its original task.

     class MySTPE extends ScheduledThreadPoolExecutor {
         ...
         protected <V> RunnableScheduledFuture<V> decorateTask(
             Runnable runnable, RunnableScheduledFuture<V> task) {
             return new MyWrapper(runnable, task);
         }
     }

     class MyWrapper<V> implements RunnableScheduledFuture<V> {
         private final Runnable runnable;
         private final RunnableScheduledFuture<V> task;
         MyWrapper(Runnable runnable, RunnableScheduledFuture<V> task) {
             this.runnable = runnable;
             this.task = task;
         }
         public Runnable originalRunnable() { return runnable; }
         // ... delegate RunnableScheduledFuture methods to task
     }

     void beforeExecute(Thread t, Runnable r) {
         if (r instanceof MyWrapper)
             r = ((MyWrapper) r).originalRunnable();
         // use r
     }

--tim

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest