[concurrency-interest] Class striped/ordered Thread Pool

Andrew Trumper andrew at intelerad.com
Wed May 16 10:21:46 EDT 2012



On 05/16/2012 04:16 AM, Dr Heinz M. Kabutz wrote:
>
> 2. I've got a nice solution utilizing the SerialExecutor approach,
> however, as Joe mentioned, shutdown is particularly challenging.  I'm
> still trying to solve that, but it is not easy.

I'm not sure I understand the "shutdown problem".. What's the issue?

> 3. Another challenge, also mentioned already in this thread, is that we
> need to carefully manage the map so that we do not get a memory leak.
> The solution I'm trying now is to delete the SerialExecutor from the map
> whenever it is empty.  This might create a lot of objects, but at least
> we don't have to worry about a memory leak.

Or you can queue a runnable on that serial executor that goes into the 
map and cleans out its own entry. Since you're executing serially it 
will execute once everything else has finished.

Given:

  interface StripedRunner {
       Object getKey(); // anything that can be used as a key in a map
       Runnable getRunnable();
  }

and this:

public class PerKeyExecutor {
   private final mMap<Object, Executor> mExecutors = new HashMap<>();
   private static final Executor mThreadCache =
       new ThreadPoolExecutor( 5, Integer.MAX_VALUE, 60L,
                               TimeUnit.SECONDS,
                             new SynchronousQueue<Runnable>() )

   public synchronized void execute( StripedRunner runnable ) {
     Executor executor = mExecutors.get( runnable.getKey() );
     if ( executor == null ) {
       mExecutors.put( runnble.getKey(), createExecutor() );
       executor = mExecutors.get( runnable.getKey() );
     }
     executor.execute( runnable.getRunnable() );
   }

   private Executor createExecutor() {
      /*
       * create a wrapper that bounds the number of
       * runnables executing at once to 1
       */
     return new BoundedExecutor( 1, mThreadCache );
   }

   // clean-up methods omitted
}

do this:

public class PerKeyExecutor {
   //...

   public void cleanUp( final Object key ) {
     execute( new StripedRunner() {
       Object getKey() { return key; }
       Runnable getRunnable() {
         dieDieDie( key );
       }
     } );
   }

   private synchronized void dieDieDie( Object key ) {
     mExecutors.remove( key );
   }
}

You can also create a special "please clean me up" StripedRunner 
instance if you really want to pass an Executor :

Runnable remeberMeForLater = PerKeyExecutor.createCleanUpRunnable();

Combine this with a stripe and it will clean up the BoundedExecutor.

- Andrew

-- 

This email or any attachments may contain confidential or legally 
privileged information intended for the sole use of the addressees. Any 
use, redistribution, disclosure, or reproduction of this information, 
except as intended, is prohibited. If you received this email in error, 
please notify the sender and remove all copies of the message, including 
any attachments.



More information about the Concurrency-interest mailing list