[concurrency-interest] proposal for AES and STPE (long)

Tim Peierls tim at peierls.net
Mon May 2 11:41:56 EDT 2005


C-I folks:

Can anyone see any problem with the following proposal? Do you see any way 
that it could break existing code? Can you think of an easier way to 
achieve the same effect?

-----

The use of FutureTask is hardwired into the submit, invokeAll, and
invokeAny methods of AbstractExecutorService, so if you want your
ExecutorService to use a custom Runnable and Future implementation other
than FutureTask, you end up having to implement the ExecutorService 
interface directly rather than extend AES.

When would you want to use a custom runnable future? Some examples:

- To identify the Runnable or Callable associated with a Future (without 
having to maintain the relationship externally).

- To detect if a submitted Runnable is already a Future, avoiding further 
wrapping.

- To add the ability to reprioritize tasks when the input queue is a 
PriorityBlockingQueue.

These are all things I've wanted to do at one time or another.


Here's a proposal to add this capability:

- Add interface j.u.c.RunnableFuture<V> implementing Runnable and Future<V>.

- Change FutureTask<V> to implement RunnableFuture<V>.

- Add to AES: protected methods
     newTaskFor(Runnable r, V v) and
     newTaskFor(Callable c),
both returning RunnableFuture<V> and implemented to return new 
FutureTask<V>(r, v) or new FutureTask<V>(c).

- Change AES submit, invokeAll, and invokeAny methods to use newTaskFor and 
RunnableFuture<V> wherever they currently have new FutureTask<V>(...) and 
FutureTask<V>.

Now if you want to provide a custom RunnableFuture, just override the 
newTaskFor methods. If you don't override them, you get the current 
behavior: FutureTask.

For example:

   public class MyCustomRunnableFuture<V> implements RunnableFuture<V> {...}

   public class MyThreadPool extends ThreadPoolExecutor {
       <V> protected RunnableFuture<V> newTaskFor(Callable<V> c) {
           return new MyCustomRunnableFuture<V>(c);
       }
       ...
   }

   ExecutorService myPool = new MyThreadPool(...);
   ...
   Future<String> f = myPool.submit(new Callable<String>() {...});
   assert f instanceof MyCustomRunnableFuture;


It would also be nice to do the same thing for scheduled tasks, but the 
situation is different; there is no AbstractScheduledExecutorService and no 
public ScheduledFutureTask<V>. Instead the following changes would allow 
one to "decorate" the internally generated runnable ScheduledFuture by 
wrapping it with another:

- Add interface j.u.c.RunnableScheduledFuture<V> implementing Runnable and 
ScheduledFuture<V>.

- Change private STPE.ScheduledFutureTask<V> to implement 
RunnableScheduledFuture<V>.

- Add to STPE: protected methods
     decorateTask(Runnable r, RunnableScheduledFuture<V> task) and
     decorateTask(Callable<V> c, RunnableScheduledFuture<V> task),
both returning RunnableScheduledFuture<V> and implemented to return their 
second arguments directly.

- Change STPE.scheduleXXX methods to wrap calls to new ScheduledFutureTask 
with decorateTask, passing the original Runnable or Callable as the first 
argument, and use the RunnableScheduleFuture type instead of 
ScheduledFutureTask where needed.

Now to decorate a RunnableScheduledFuture<V> with your own, override the 
decorateTask methods to do something other than return their second 
arguments directly -- probably by creating a delegating wrapper around the 
second argument that keeps a reference to the original Runnable or Callable.

For example:

   public class MyScheduleTask<V> implements RunnableScheduledFuture<V> {
     ...
   }

   public class MyScheduledThreadPool extends ScheduledThreadPoolExecutor {
       <V> protected RunnableScheduledFuture<V> decorateTask(
           Runnable r, RunnableScheduledFuture<V> rsf) {

           return new MyScheduledTask<V>(r, rsf);
       }
       ...
   }

   ScheduledExecutorService mySkd = new MyScheduledThreadPool(...);
   ScheduledFuture<String> f = mySkd.schedule(2, MINUTES, runnableTask);
   assert f instanceof MyScheduledTask;

-----

--tim



More information about the Concurrency-interest mailing list