Merge changes from 2.1 release branch back into trunk

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/jcs/trunk@1782354 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/README.md b/README.md
index 78ebaca..49374d7 100644
--- a/README.md
+++ b/README.md
@@ -62,7 +62,7 @@
 <dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-jcs</artifactId>
-  <version>2.1</version>
+  <version>2.0</version>
 </dependency>
 ```
 
diff --git a/commons-jcs-core/pom.xml b/commons-jcs-core/pom.xml
index ea02976..1b35a29 100644
--- a/commons-jcs-core/pom.xml
+++ b/commons-jcs-core/pom.xml
@@ -33,9 +33,9 @@
   <name>Apache Commons JCS :: Core</name>
 
   <scm>
-    <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-core</connection>
-    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-core</developerConnection>
-    <url>http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-core</url>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-core</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-core</developerConnection>
+    <url>http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core</url>
   </scm>
 
   <properties>
@@ -154,9 +154,6 @@
               <exclude>**/UDPDiscoveryUnitTest.java</exclude>
               <!-- Causes hang in Continuum -->
               <exclude>**/UDPDiscoverySenderUnitTest.java</exclude>
-              <!-- The ones that fail may be different for you. -->
-              <!-- <exclude>**/JDBCDiskCacheRemovalUnitTest.java</exclude> -->
-              <!-- <exclude>**/JDBCDiskCacheUnitTest.java</exclude> -->
             </excludes>
           </configuration>
         </plugin>
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/JCS.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/JCS.java
index 304df37..a51da23 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/JCS.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/JCS.java
@@ -130,6 +130,22 @@
     }
 
     /**
+     * Shut down the cache manager and set the instance to null
+     */
+    public static void shutdown()
+    {
+        synchronized ( JCS.class )
+        {
+            if ( cacheMgr != null && cacheMgr.isInitialized())
+            {
+            	cacheMgr.shutDown();
+            }
+
+            cacheMgr = null;
+        }
+    }
+
+    /**
      * Helper method which checks to make sure the cacheMgr class field is set, and if not requests
      * an instance from CacheManagerFactory.
      *
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/AbstractRemoteAuxiliaryCache.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/AbstractRemoteAuxiliaryCache.java
index 653220d..0b3d656 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/AbstractRemoteAuxiliaryCache.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/AbstractRemoteAuxiliaryCache.java
@@ -26,8 +26,8 @@
 import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
-import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
@@ -77,7 +77,7 @@
     private IRemoteCacheAttributes remoteCacheAttributes;
 
     /** A thread pool for gets if configured. */
-    private ThreadPoolExecutor pool = null;
+    private ExecutorService pool = null;
 
     /** Should we get asynchronously using a pool. */
     private boolean usePoolForGet = false;
@@ -113,15 +113,12 @@
 
         if ( getRemoteCacheAttributes().getGetTimeoutMillis() > 0 )
         {
-            pool = ThreadPoolManager.getInstance().getPool( getRemoteCacheAttributes().getThreadPoolName() );
+            pool = ThreadPoolManager.getInstance().getExecutorService( getRemoteCacheAttributes().getThreadPoolName() );
             if ( log.isDebugEnabled() )
             {
                 log.debug( "Thread Pool = " + pool );
             }
-            if ( pool != null )
-            {
-                usePoolForGet = true;
-            }
+            usePoolForGet = true;
         }
     }
 
@@ -145,7 +142,7 @@
                 getRemoteCacheListener().dispose();
             }
         }
-        catch ( Exception ex )
+        catch ( IOException ex )
         {
             log.error( "Couldn't dispose", ex );
             handleException( ex, "Failed to dispose [" + cacheName + "]", ICacheEventLogger.DISPOSE_EVENT );
@@ -573,8 +570,7 @@
 
         if ( pool != null )
         {
-            elems.add(new StatElement<Integer>( "Pool Size", Integer.valueOf(pool.getPoolSize()) ) );
-            elems.add(new StatElement<Integer>( "Maximum Pool Size", Integer.valueOf(pool.getMaximumPoolSize()) ) );
+            elems.add(new StatElement<ExecutorService>( "Pool", pool ) );
         }
 
         if ( getRemoteCacheService() instanceof ZombieCacheServiceNonLocal )
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/AbstractCacheEventQueue.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/AbstractCacheEventQueue.java
index 216a94d..9f37b0c 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/AbstractCacheEventQueue.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/AbstractCacheEventQueue.java
@@ -64,9 +64,6 @@
     /** in milliseconds */
     private int waitBeforeRetry;
 
-    /** this is true if there is any worker thread. */
-    private final AtomicBoolean alive = new AtomicBoolean(false);
-
     /**
      * This means that the queue is functional. If we reached the max number of failures, the queue
      * is marked as non functional and will never work again.
@@ -108,21 +105,27 @@
      * If they queue has an active thread it is considered alive.
      * <p>
      * @return The alive value
+     * 
+     * @deprecated The alive-logic is not used 
      */
-    @Override
+    @Deprecated
+	@Override
     public boolean isAlive()
     {
-        return alive.get();
+        return true;
     }
 
     /**
      * Sets whether the queue is actively processing -- if there are working threads.
      * <p>
      * @param aState
+     * 
+     * @deprecated The alive-logic is not used 
      */
-    public void setAlive( boolean aState )
+    @Deprecated
+	public void setAlive( boolean aState )
     {
-        alive.set(aState);
+        // do nothing
     }
 
     /**
@@ -179,17 +182,9 @@
      * @throws IOException
      */
     @Override
-    public synchronized void addPutEvent( ICacheElement<K, V> ce )
-        throws IOException
+    public void addPutEvent( ICacheElement<K, V> ce )
     {
-        if ( isWorking() )
-        {
-            put( new PutEvent( ce ) );
-        }
-        else if ( log.isWarnEnabled() )
-        {
-            log.warn( "Not enqueuing Put Event for [" + this + "] because it's non-functional." );
-        }
+        put( new PutEvent( ce ) );
     }
 
     /**
@@ -200,54 +195,28 @@
      * @throws IOException
      */
     @Override
-    public synchronized void addRemoveEvent( K key )
-        throws IOException
+    public void addRemoveEvent( K key )
     {
-        if ( isWorking() )
-        {
-            put( new RemoveEvent( key ) );
-        }
-        else if ( log.isWarnEnabled() )
-        {
-            log.warn( "Not enqueuing Remove Event for [" + this + "] because it's non-functional." );
-        }
+        put( new RemoveEvent( key ) );
     }
 
     /**
      * This adds a remove all event to the queue. When it is processed, all elements will be removed
      * from the cache.
-     * <p>
-     * @throws IOException
      */
     @Override
-    public synchronized void addRemoveAllEvent()
-        throws IOException
+    public void addRemoveAllEvent()
     {
-        if ( isWorking() )
-        {
-            put( new RemoveAllEvent() );
-        }
-        else if ( log.isWarnEnabled() )
-        {
-            log.warn( "Not enqueuing RemoveAll Event for [" + this + "] because it's non-functional." );
-        }
+        put( new RemoveAllEvent() );
     }
 
     /**
-     * @throws IOException
+     * This adds a dispose event to the queue. When it is processed, the cache is shut down
      */
     @Override
-    public synchronized void addDisposeEvent()
-        throws IOException
+    public void addDisposeEvent()
     {
-        if ( isWorking() )
-        {
-            put( new DisposeEvent() );
-        }
-        else if ( log.isWarnEnabled() )
-        {
-            log.warn( "Not enqueuing Dispose Event for [" + this + "] because it's non-functional." );
-        }
+        put( new DisposeEvent() );
     }
 
     /**
@@ -293,8 +262,7 @@
                         log.warn( "Error while running event from Queue: " + this
                             + ". Dropping Event and marking Event Queue as non-functional." );
                     }
-                    setWorking( false );
-                    setAlive( false );
+                    destroy();
                     return;
                 }
                 if ( log.isInfoEnabled() )
@@ -312,10 +280,7 @@
                     {
                         log.warn( "Interrupted while sleeping for retry on event " + this + "." );
                     }
-                    // TODO consider if this is best. maybe we should just
-                    // destroy
-                    setWorking( false );
-                    setAlive( false );
+                    destroy();
                 }
             }
         }
@@ -342,10 +307,8 @@
          * Constructor for the PutEvent object.
          * <p>
          * @param ice
-         * @throws IOException
          */
         PutEvent( ICacheElement<K, V> ice )
-            throws IOException
         {
             this.ice = ice;
         }
@@ -391,10 +354,8 @@
          * Constructor for the RemoveEvent object
          * <p>
          * @param key
-         * @throws IOException
          */
         RemoveEvent( K key )
-            throws IOException
         {
             this.key = key;
         }
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/CacheEventQueue.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/CacheEventQueue.java
index 58fc27b..bf2758f 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/CacheEventQueue.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/CacheEventQueue.java
@@ -1,9 +1,5 @@
 package org.apache.commons.jcs.engine;
 
-import java.util.ArrayList;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -24,35 +20,19 @@
  */
 
 import org.apache.commons.jcs.engine.behavior.ICacheListener;
-import org.apache.commons.jcs.engine.stats.StatElement;
-import org.apache.commons.jcs.engine.stats.Stats;
-import org.apache.commons.jcs.engine.stats.behavior.IStatElement;
-import org.apache.commons.jcs.engine.stats.behavior.IStats;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.apache.commons.jcs.utils.threadpool.PoolConfiguration;
+import org.apache.commons.jcs.utils.threadpool.PoolConfiguration.WhenBlockedPolicy;
+import org.apache.commons.jcs.utils.threadpool.ThreadPoolManager;
 
 /**
  * An event queue is used to propagate ordered cache events to one and only one target listener.
- * <p>
- * This is a modified version of the experimental version. It should lazy initialize the processor
- * thread, and kill the thread if the queue goes empty for a specified period, now set to 1 minute.
- * If something comes in after that a new processor thread should be created.
  */
 public class CacheEventQueue<K, V>
-    extends AbstractCacheEventQueue<K, V>
+    extends PooledCacheEventQueue<K, V>
 {
-    /** The logger. */
-    private static final Log log = LogFactory.getLog( CacheEventQueue.class );
-
     /** The type of queue -- there are pooled and single */
     private static final QueueType queueType = QueueType.SINGLE;
 
-    /** the thread that works the queue. */
-    private Thread processorThread;
-
-    /** Queue implementation */
-    private LinkedBlockingQueue<AbstractCacheEvent> queue = new LinkedBlockingQueue<AbstractCacheEvent>();
-
     /**
      * Constructs with the specified listener and the cache name.
      * <p>
@@ -77,7 +57,29 @@
     public CacheEventQueue( ICacheListener<K, V> listener, long listenerId, String cacheName, int maxFailure,
                             int waitBeforeRetry )
     {
-        initialize( listener, listenerId, cacheName, maxFailure, waitBeforeRetry );
+        super( listener, listenerId, cacheName, maxFailure, waitBeforeRetry, null );
+    }
+
+    /**
+     * Initializes the queue.
+     * <p>
+     * @param listener
+     * @param listenerId
+     * @param cacheName
+     * @param maxFailure
+     * @param waitBeforeRetry
+     * @param threadPoolName
+     */
+    @Override
+    protected void initialize( ICacheListener<K, V> listener, long listenerId, String cacheName, int maxFailure,
+                            int waitBeforeRetry, String threadPoolName )
+    {
+        super.initialize(listener, listenerId, cacheName, maxFailure, waitBeforeRetry);
+
+        // create a default pool with one worker thread to mimic the SINGLE queue behavior
+        pool = ThreadPoolManager.getInstance().createPool(
+        		new PoolConfiguration(false, 0, 1, 0, getWaitToDieMillis(), WhenBlockedPolicy.RUN, 0),
+        		"CacheEventQueue.QProcessor-" + getCacheName());
     }
 
     /**
@@ -90,192 +92,4 @@
     {
         return queueType;
     }
-
-    /**
-     * Kill the processor thread and indicate that the queue is destroyed and no longer alive, but it
-     * can still be working.
-     */
-    protected void stopProcessing()
-    {
-        setAlive(false);
-        processorThread = null;
-    }
-
-    /**
-     * Event Q is empty.
-     * <p>
-     * Calling destroy interrupts the processor thread.
-     */
-    @Override
-    public void destroy()
-    {
-        if ( isAlive() )
-        {
-            setAlive(false);
-
-            if ( log.isInfoEnabled() )
-            {
-                log.info( "Destroying queue, stats =  " + getStatistics() );
-            }
-
-            if ( processorThread != null )
-            {
-                processorThread.interrupt();
-                processorThread = null;
-            }
-
-            if ( log.isInfoEnabled() )
-            {
-                log.info( "Cache event queue destroyed: " + this );
-            }
-        }
-        else
-        {
-            if ( log.isInfoEnabled() )
-            {
-                log.info( "Destroy was called after queue was destroyed. Doing nothing. Stats =  " + getStatistics() );
-            }
-        }
-    }
-
-    /**
-     * Adds an event to the queue.
-     * <p>
-     * @param event
-     */
-    @Override
-    protected void put( AbstractCacheEvent event )
-    {
-        if ( log.isDebugEnabled() )
-        {
-            log.debug( "Event entering Queue for " + getCacheName() + ": " + event );
-        }
-
-        queue.offer(event);
-
-        if ( isWorking() )
-        {
-            if ( !isAlive() )
-            {
-                setAlive(true);
-                processorThread = new QProcessor();
-                processorThread.start();
-                if ( log.isInfoEnabled() )
-                {
-                    log.info( "Cache event queue created: " + this );
-                }
-            }
-        }
-    }
-
-    // /////////////////////////// Inner classes /////////////////////////////
-
-    /**
-     * This is the thread that works the queue.
-     * <p>
-     * @author asmuts
-     * @created January 15, 2002
-     */
-    protected class QProcessor
-        extends Thread
-    {
-        /**
-         * Constructor for the QProcessor object
-         * <p>
-         * @param aQueue the event queue to take items from.
-         */
-        QProcessor()
-        {
-            super( "CacheEventQueue.QProcessor-" + getCacheName() );
-            setDaemon( true );
-        }
-
-        /**
-         * Main processing method for the QProcessor object.
-         * <p>
-         * Waits for a specified time (waitToDieMillis) for something to come in and if no new
-         * events come in during that period the run method can exit and the thread is dereferenced.
-         */
-        @Override
-        public void run()
-        {
-
-            while ( CacheEventQueue.this.isAlive() )
-            {
-                AbstractCacheEvent event = null;
-
-                try
-                {
-                    event = queue.poll(getWaitToDieMillis(), TimeUnit.MILLISECONDS);
-                }
-                catch (InterruptedException e)
-                {
-                    // is ok
-                }
-
-                if ( log.isDebugEnabled() )
-                {
-                    log.debug( "Event from queue = " + event );
-                }
-
-                if ( event == null )
-                {
-                    stopProcessing();
-                }
-
-                if ( event != null && isWorking() && CacheEventQueue.this.isAlive() )
-                {
-                    event.run();
-                }
-            }
-            if ( log.isDebugEnabled() )
-            {
-                log.debug( "QProcessor exiting for " + getCacheName() );
-            }
-        }
-    }
-
-    /**
-     * This method returns semi-structured data on this queue.
-     * <p>
-     * @see org.apache.commons.jcs.engine.behavior.ICacheEventQueue#getStatistics()
-     * @return information on the status and history of the queue
-     */
-    @Override
-    public IStats getStatistics()
-    {
-        IStats stats = new Stats();
-        stats.setTypeName( "Cache Event Queue" );
-
-        ArrayList<IStatElement<?>> elems = new ArrayList<IStatElement<?>>();
-
-        elems.add(new StatElement<Boolean>( "Working", Boolean.valueOf(this.isWorking()) ) );
-        elems.add(new StatElement<Boolean>( "Alive", Boolean.valueOf(this.isAlive()) ) );
-        elems.add(new StatElement<Boolean>( "Empty", Boolean.valueOf(this.isEmpty()) ) );
-        elems.add(new StatElement<Integer>( "Size", Integer.valueOf(this.size()) ) );
-
-        stats.setStatElements( elems );
-
-        return stats;
-    }
-
-    /**
-     * @return whether there are any items in the queue.
-     */
-    @Override
-    public boolean isEmpty()
-    {
-        return queue.isEmpty();
-    }
-
-    /**
-     * Returns the number of elements in the queue.
-     * <p>
-     * @return number of items in the queue.
-     */
-    @Override
-    public int size()
-    {
-        return queue.size();
-    }
 }
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/PooledCacheEventQueue.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/PooledCacheEventQueue.java
index 81dfe23..e4b1089 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/PooledCacheEventQueue.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/PooledCacheEventQueue.java
@@ -2,6 +2,7 @@
 
 import java.util.ArrayList;
 import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ThreadPoolExecutor;
 
 /*
@@ -52,7 +53,10 @@
     private static final QueueType queueType = QueueType.POOLED;
 
     /** The Thread Pool to execute events with. */
-    private ThreadPoolExecutor pool = null;
+    protected ExecutorService pool = null;
+
+    /** The Thread Pool queue */
+    protected BlockingQueue<Runnable> queue = null;
 
     /**
      * Constructor for the CacheEventQueue object
@@ -86,8 +90,13 @@
         super.initialize(listener, listenerId, cacheName, maxFailure, waitBeforeRetry);
 
         // this will share the same pool with other event queues by default.
-        pool = ThreadPoolManager.getInstance().getPool(
+        pool = ThreadPoolManager.getInstance().getExecutorService(
                 (threadPoolName == null) ? "cache_event_queue" : threadPoolName );
+        
+        if (pool instanceof ThreadPoolExecutor)
+        {
+        	queue = ((ThreadPoolExecutor) pool).getQueue();
+        }
     }
 
     /**
@@ -105,9 +114,9 @@
     @Override
     public synchronized void destroy()
     {
-        if ( isAlive() )
+        if ( isWorking() )
         {
-            setAlive(false);
+            setWorking(false);
             pool.shutdownNow();
             if ( log.isInfoEnabled() )
             {
@@ -138,20 +147,15 @@
 
         ArrayList<IStatElement<?>> elems = new ArrayList<IStatElement<?>>();
 
-        elems.add(new StatElement<Boolean>( "Working", Boolean.valueOf(super.isWorking()) ) );
-        elems.add(new StatElement<Boolean>( "Alive", Boolean.valueOf(this.isAlive()) ) );
+        elems.add(new StatElement<Boolean>( "Working", Boolean.valueOf(isWorking()) ) );
         elems.add(new StatElement<Boolean>( "Empty", Boolean.valueOf(this.isEmpty()) ) );
 
-        if ( pool.getQueue() != null )
+        if ( queue != null )
         {
-            BlockingQueue<Runnable> bb = pool.getQueue();
-            elems.add(new StatElement<Integer>( "Queue Size", Integer.valueOf(bb.size()) ) );
-            elems.add(new StatElement<Integer>( "Queue Capacity", Integer.valueOf(bb.remainingCapacity()) ) );
+            elems.add(new StatElement<Integer>( "Queue Size", Integer.valueOf(queue.size()) ) );
+            elems.add(new StatElement<Integer>( "Queue Capacity", Integer.valueOf(queue.remainingCapacity()) ) );
         }
 
-        elems.add(new StatElement<Integer>( "Pool Size", Integer.valueOf(pool.getPoolSize()) ) );
-        elems.add(new StatElement<Integer>( "Maximum Pool Size", Integer.valueOf(pool.getMaximumPoolSize()) ) );
-
         stats.setStatElements( elems );
 
         return stats;
@@ -166,32 +170,25 @@
     @Override
     public boolean isEmpty()
     {
-        if ( pool.getQueue() == null )
-        {
-            return true;
-        }
-        else
-        {
-            return pool.getQueue().size() == 0;
-        }
+        return size() == 0;
     }
 
     /**
      * Returns the number of elements in the queue. If the queue cannot determine the size
-     * accurately it will return 1.
+     * accurately it will return 0.
      * <p>
      * @return number of items in the queue.
      */
     @Override
     public int size()
     {
-        if ( pool.getQueue() == null )
+        if ( queue == null )
         {
             return 0;
         }
         else
         {
-            return pool.getQueue().size();
+            return queue.size();
         }
     }
 }
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/event/ElementEventQueue.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/event/ElementEventQueue.java
index 1a6e9bd..44ab573 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/event/ElementEventQueue.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/event/ElementEventQueue.java
@@ -20,14 +20,14 @@
  */
 
 import java.io.IOException;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.ExecutorService;
 
 import org.apache.commons.jcs.engine.control.event.behavior.IElementEvent;
 import org.apache.commons.jcs.engine.control.event.behavior.IElementEventHandler;
 import org.apache.commons.jcs.engine.control.event.behavior.IElementEventQueue;
-import org.apache.commons.jcs.utils.threadpool.DaemonThreadFactory;
+import org.apache.commons.jcs.utils.threadpool.PoolConfiguration;
+import org.apache.commons.jcs.utils.threadpool.PoolConfiguration.WhenBlockedPolicy;
+import org.apache.commons.jcs.utils.threadpool.ThreadPoolManager;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -45,20 +45,16 @@
     /** shutdown or not */
     private boolean destroyed = false;
 
-    /** The event queue */
-    private LinkedBlockingQueue<Runnable> queue;
-
     /** The worker thread pool. */
-    private ThreadPoolExecutor queueProcessor;
+    private ExecutorService queueProcessor;
 
     /**
      * Constructor for the ElementEventQueue object
      */
     public ElementEventQueue()
     {
-        queue = new LinkedBlockingQueue<Runnable>();
-        queueProcessor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
-                queue, new DaemonThreadFactory(THREAD_PREFIX));
+        queueProcessor = ThreadPoolManager.getInstance().createPool(
+        		new PoolConfiguration(false, 0, 1, 1, 0, WhenBlockedPolicy.RUN, 1), THREAD_PREFIX);
 
         if ( log.isDebugEnabled() )
         {
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractDoubleLinkedListMemoryCache.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractDoubleLinkedListMemoryCache.java
index b5523d7..5f85104 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractDoubleLinkedListMemoryCache.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractDoubleLinkedListMemoryCache.java
@@ -20,15 +20,10 @@
  */
 
 import java.io.IOException;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
-import org.apache.commons.jcs.engine.CacheConstants;
 import org.apache.commons.jcs.engine.behavior.ICacheElement;
 import org.apache.commons.jcs.engine.control.CompositeCache;
 import org.apache.commons.jcs.engine.control.group.GroupAttrName;
@@ -199,74 +194,6 @@
     }
 
     /**
-     * Get an item from the cache If the item is found, it is removed from the list and added first.
-     * <p>
-     *
-     * @param key
-     *            Identifies item to find
-     * @return ICacheElement&lt;K, V&gt; if found, else null
-     * @throws IOException
-     */
-    @Override
-    public final ICacheElement<K, V> get(K key) throws IOException
-    {
-        ICacheElement<K, V> ce = null;
-
-        if (log.isDebugEnabled())
-        {
-            log.debug(getCacheName() + ": getting item for key " + key);
-        }
-
-        MemoryElementDescriptor<K, V> me = map.get(key);
-
-        if (me != null)
-        {
-            hitCnt.incrementAndGet();
-
-            lock.lock();
-            try
-            {
-                ce = me.getCacheElement();
-                // ABSTRACT
-                adjustListForGet(me);
-            }
-            finally
-            {
-                lock.unlock();
-            }
-
-            if (log.isDebugEnabled())
-            {
-                log.debug(getCacheName() + ": LRUMemoryCache hit for " + key);
-            }
-        }
-        else
-        {
-            missCnt.incrementAndGet();
-
-            if (log.isDebugEnabled())
-            {
-                log.debug(getCacheName() + ": LRUMemoryCache miss for " + key);
-            }
-        }
-
-        if (log.isDebugEnabled())
-        {
-            verifyCache();
-        }
-
-        return ce;
-    }
-
-    /**
-     * Adjust the list as needed for a get. This allows children to control the algorithm
-     * <p>
-     *
-     * @param me
-     */
-    protected abstract void adjustListForGet(MemoryElementDescriptor<K, V> me);
-
-    /**
      * This instructs the memory cache to remove the <i>numberToFree</i> according to its eviction
      * policy. For example, the LRUMemoryCache will remove the <i>numberToFree</i> least recently
      * used items. These will be spooled to disk if a disk auxiliary is available.
@@ -343,116 +270,61 @@
     }
 
     /**
-     * Removes an item from the cache. This method handles hierarchical removal. If the key is a
-     * String and ends with the CacheConstants.NAME_COMPONENT_DELIMITER, then all items with keys
-     * starting with the argument String will be removed.
-     * <p>
-     *
-     * @param key
-     * @return true if the removal was successful
-     * @throws IOException
+     * @see org.apache.commons.jcs.engine.memory.AbstractMemoryCache#get(java.lang.Object)
      */
     @Override
-    public boolean remove(K key) throws IOException
+    public ICacheElement<K, V> get(K key) throws IOException
     {
+        ICacheElement<K, V> ce = super.get(key);
+
         if (log.isDebugEnabled())
         {
-            log.debug("removing item for key: " + key);
+            verifyCache();
         }
 
-        boolean removed = false;
-
-        // handle partial removal
-        if (key instanceof String && ((String) key).endsWith(CacheConstants.NAME_COMPONENT_DELIMITER))
-        {
-            // remove all keys of the same name hierarchy.
-            for (Iterator<Map.Entry<K, MemoryElementDescriptor<K, V>>> itr = map.entrySet().iterator(); itr.hasNext();)
-            {
-                Map.Entry<K, MemoryElementDescriptor<K, V>> entry = itr.next();
-                K k = entry.getKey();
-
-                if (k instanceof String && ((String) k).startsWith(key.toString()))
-                {
-                    lock.lock();
-                    try
-                    {
-                        list.remove(entry.getValue());
-                        itr.remove();
-                        removed = true;
-                    }
-                    finally
-                    {
-                        lock.unlock();
-                    }
-                }
-            }
-        }
-        else if (key instanceof GroupAttrName && ((GroupAttrName<?>) key).attrName == null)
-        {
-            // remove all keys of the same name hierarchy.
-            for (Iterator<Map.Entry<K, MemoryElementDescriptor<K, V>>> itr = map.entrySet().iterator(); itr.hasNext();)
-            {
-                Map.Entry<K, MemoryElementDescriptor<K, V>> entry = itr.next();
-                K k = entry.getKey();
-
-                if (k instanceof GroupAttrName && ((GroupAttrName<?>) k).groupId.equals(((GroupAttrName<?>) key).groupId))
-                {
-                    lock.lock();
-                    try
-                    {
-                        list.remove(entry.getValue());
-                        itr.remove();
-                        removed = true;
-                    }
-                    finally
-                    {
-                        lock.unlock();
-                    }
-                }
-            }
-        }
-        else
-        {
-            // remove single item.
-            lock.lock();
-            try
-            {
-                MemoryElementDescriptor<K, V> me = map.remove(key);
-                if (me != null)
-                {
-                    list.remove(me);
-                    removed = true;
-                }
-            }
-            finally
-            {
-                lock.unlock();
-            }
-        }
-
-        return removed;
+        return ce;
     }
 
     /**
-     * Remove all of the elements from both the Map and the linked list implementation. Overrides
-     * base class.
+     * Adjust the list as needed for a get. This allows children to control the algorithm
      * <p>
      *
-     * @throws IOException
+     * @param me
+     */
+    protected abstract void adjustListForGet(MemoryElementDescriptor<K, V> me);
+
+    /**
+     * Update control structures after get
+     * (guarded by the lock)
+     *
+     * @param me the memory element descriptor
      */
     @Override
-    public void removeAll() throws IOException
+    protected void lockedGetElement(MemoryElementDescriptor<K, V> me)
     {
-        lock.lock();
-        try
-        {
-            list.removeAll();
-            map.clear();
-        }
-        finally
-        {
-            lock.unlock();
-        }
+        adjustListForGet(me);
+    }
+
+    /**
+     * Remove element from control structure
+     * (guarded by the lock)
+     *
+     * @param me the memory element descriptor
+     */
+    @Override
+    protected void lockedRemoveElement(MemoryElementDescriptor<K, V> me)
+    {
+        list.remove(me);
+    }
+
+    /**
+     * Removes all cached items from the cache control structures.
+     * (guarded by the lock)
+     */
+    @Override
+    protected void lockedRemoveAll()
+    {
+        list.removeAll();
     }
 
     // --------------------------- internal methods (linked list implementation)
@@ -631,17 +503,6 @@
     }
 
     /**
-     * Get an Array of the keys for all elements in the memory cache
-     *
-     * @return An Object[]
-     */
-    @Override
-    public Set<K> getKeySet()
-    {
-        return new LinkedHashSet<K>(map.keySet());
-    }
-
-    /**
      * This returns semi-structured information on the memory cache, such as the size, put count,
      * hit count, and miss count.
      * <p>
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractMemoryCache.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractMemoryCache.java
index 87929fa..dc4bf5c 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractMemoryCache.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractMemoryCache.java
@@ -22,16 +22,19 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
-import org.apache.commons.jcs.engine.CacheStatus;
+import org.apache.commons.jcs.engine.CacheConstants;
 import org.apache.commons.jcs.engine.behavior.ICacheElement;
 import org.apache.commons.jcs.engine.behavior.ICompositeCacheAttributes;
 import org.apache.commons.jcs.engine.control.CompositeCache;
+import org.apache.commons.jcs.engine.control.group.GroupAttrName;
 import org.apache.commons.jcs.engine.memory.behavior.IMemoryCache;
 import org.apache.commons.jcs.engine.memory.util.MemoryElementDescriptor;
 import org.apache.commons.jcs.engine.stats.StatElement;
@@ -43,9 +46,6 @@
 
 /**
  * This base includes some common code for memory caches.
- * <p>
- * This keeps a static reference to a memory shrinker clock daemon. If this region is configured to
- * use the shrinker, the clock daemon will be setup to run the shrinker on this region.
  */
 public abstract class AbstractMemoryCache<K, V>
     implements IMemoryCache<K, V>
@@ -59,9 +59,6 @@
     /** The cache region this store is associated with */
     private CompositeCache<K, V> cache;
 
-    /** status */
-    private CacheStatus status;
-
     /** How many to spool at a time. */
     protected int chunkSize;
 
@@ -96,8 +93,6 @@
         this.cache = hub;
 
         this.map = createMap();
-
-        this.status = CacheStatus.ALIVE;
     }
 
     /**
@@ -109,28 +104,6 @@
     public abstract Map<K, MemoryElementDescriptor<K, V>> createMap();
 
     /**
-     * Removes an item from the cache
-     * <p>
-     * @param key Identifies item to be removed
-     * @return Description of the Return Value
-     * @throws IOException Description of the Exception
-     */
-    @Override
-    public abstract boolean remove( K key )
-        throws IOException;
-
-    /**
-     * Get an item from the cache
-     * <p>
-     * @param key Description of the Parameter
-     * @return Description of the Return Value
-     * @throws IOException Description of the Exception
-     */
-    @Override
-    public abstract ICacheElement<K, V> get( K key )
-        throws IOException;
-
-    /**
      * Gets multiple items from the cache based on the given set of keys.
      * <p>
      * @param keys
@@ -203,26 +176,32 @@
         throws IOException;
 
     /**
-     * Get a set of the keys for all elements in the memory cache
-     * <p>
-     * @return A set of the key type
-     */
-    @Override
-    public abstract Set<K> getKeySet();
-
-    /**
      * Removes all cached items from the cache.
      * <p>
      * @throws IOException
      */
     @Override
-    public void removeAll()
-        throws IOException
+    public void removeAll() throws IOException
     {
-        map.clear();
+        lock.lock();
+        try
+        {
+            lockedRemoveAll();
+            map.clear();
+        }
+        finally
+        {
+            lock.unlock();
+        }
     }
 
     /**
+     * Removes all cached items from the cache control structures.
+     * (guarded by the lock)
+     */
+    protected abstract void lockedRemoveAll();
+
+    /**
      * Prepares for shutdown. Reset statistics
      * <p>
      * @throws IOException
@@ -270,16 +249,6 @@
     }
 
     /**
-     * Returns the cache status.
-     * <p>
-     * @return The status value
-     */
-    public CacheStatus getStatus()
-    {
-        return this.status;
-    }
-
-    /**
      * Returns the cache (aka "region") name.
      * <p>
      * @return The cacheName value
@@ -351,4 +320,204 @@
     {
         return this.cache;
     }
+
+    /**
+     * Remove all keys of the same group hierarchy.
+     * @param key the key
+     * @return true if something has been removed
+     */
+    protected boolean removeByGroup(K key)
+    {
+        boolean removed = false;
+
+        // remove all keys of the same group hierarchy.
+        for (Iterator<Map.Entry<K, MemoryElementDescriptor<K, V>>> itr = map.entrySet().iterator(); itr.hasNext();)
+        {
+            Map.Entry<K, MemoryElementDescriptor<K, V>> entry = itr.next();
+            K k = entry.getKey();
+
+            if (k instanceof GroupAttrName && ((GroupAttrName<?>) k).groupId.equals(((GroupAttrName<?>) key).groupId))
+            {
+                lock.lock();
+                try
+                {
+                    itr.remove();
+                    lockedRemoveElement(entry.getValue());
+                    removed = true;
+                }
+                finally
+                {
+                    lock.unlock();
+                }
+            }
+        }
+
+        return removed;
+    }
+
+    /**
+     * Remove all keys of the same name hierarchy.
+     *
+     * @param key the key
+     * @return true if something has been removed
+     */
+    protected boolean removeByHierarchy(K key)
+    {
+        boolean removed = false;
+
+        // remove all keys of the same name hierarchy.
+        for (Iterator<Map.Entry<K, MemoryElementDescriptor<K, V>>> itr = map.entrySet().iterator(); itr.hasNext();)
+        {
+            Map.Entry<K, MemoryElementDescriptor<K, V>> entry = itr.next();
+            K k = entry.getKey();
+
+            if (k instanceof String && ((String) k).startsWith(key.toString()))
+            {
+                lock.lock();
+                try
+                {
+                    itr.remove();
+                    lockedRemoveElement(entry.getValue());
+                    removed = true;
+                }
+                finally
+                {
+                    lock.unlock();
+                }
+            }
+        }
+
+        return removed;
+    }
+
+    /**
+     * Remove element from control structure
+     * (guarded by the lock)
+     *
+     * @param me the memory element descriptor
+     */
+    protected abstract void lockedRemoveElement(MemoryElementDescriptor<K, V> me);
+
+    /**
+     * Removes an item from the cache. This method handles hierarchical removal. If the key is a
+     * String and ends with the CacheConstants.NAME_COMPONENT_DELIMITER, then all items with keys
+     * starting with the argument String will be removed.
+     * <p>
+     *
+     * @param key
+     * @return true if the removal was successful
+     * @throws IOException
+     */
+    @Override
+    public boolean remove(K key) throws IOException
+    {
+        if (log.isDebugEnabled())
+        {
+            log.debug("removing item for key: " + key);
+        }
+
+        boolean removed = false;
+
+        // handle partial removal
+        if (key instanceof String && ((String) key).endsWith(CacheConstants.NAME_COMPONENT_DELIMITER))
+        {
+            removed = removeByHierarchy(key);
+        }
+        else if (key instanceof GroupAttrName && ((GroupAttrName<?>) key).attrName == null)
+        {
+            removed = removeByGroup(key);
+        }
+        else
+        {
+            // remove single item.
+            lock.lock();
+            try
+            {
+                MemoryElementDescriptor<K, V> me = map.remove(key);
+                if (me != null)
+                {
+                    lockedRemoveElement(me);
+                    removed = true;
+                }
+            }
+            finally
+            {
+                lock.unlock();
+            }
+        }
+
+        return removed;
+    }
+
+    /**
+     * Get an Array of the keys for all elements in the memory cache
+     *
+     * @return An Object[]
+     */
+    @Override
+    public Set<K> getKeySet()
+    {
+        return new LinkedHashSet<K>(map.keySet());
+    }
+
+    /**
+     * Get an item from the cache.
+     * <p>
+     *
+     * @param key Identifies item to find
+     * @return ICacheElement&lt;K, V&gt; if found, else null
+     * @throws IOException
+     */
+    @Override
+    public ICacheElement<K, V> get(K key) throws IOException
+    {
+        ICacheElement<K, V> ce = null;
+
+        if (log.isDebugEnabled())
+        {
+            log.debug(getCacheName() + ": getting item for key " + key);
+        }
+
+        MemoryElementDescriptor<K, V> me = map.get(key);
+
+        if (me != null)
+        {
+            hitCnt.incrementAndGet();
+            ce = me.getCacheElement();
+
+            lock.lock();
+            try
+            {
+                lockedGetElement(me);
+            }
+            finally
+            {
+                lock.unlock();
+            }
+
+            if (log.isDebugEnabled())
+            {
+                log.debug(getCacheName() + ": MemoryCache hit for " + key);
+            }
+        }
+        else
+        {
+            missCnt.incrementAndGet();
+
+            if (log.isDebugEnabled())
+            {
+                log.debug(getCacheName() + ": MemoryCache miss for " + key);
+            }
+        }
+
+        return ce;
+    }
+
+    /**
+     * Update control structures after get
+     * (guarded by the lock)
+     *
+     * @param me the memory element descriptor
+     */
+    protected abstract void lockedGetElement(MemoryElementDescriptor<K, V> me);
 }
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/lru/LHMLRUMemoryCache.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/lru/LHMLRUMemoryCache.java
index b6ff779..2679fb7 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/lru/LHMLRUMemoryCache.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/lru/LHMLRUMemoryCache.java
@@ -21,15 +21,10 @@
 
 import java.io.IOException;
 import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
 import java.util.Map;
-import java.util.Set;
 
-import org.apache.commons.jcs.engine.CacheConstants;
 import org.apache.commons.jcs.engine.behavior.ICacheElement;
 import org.apache.commons.jcs.engine.control.CompositeCache;
-import org.apache.commons.jcs.engine.control.group.GroupAttrName;
 import org.apache.commons.jcs.engine.memory.AbstractMemoryCache;
 import org.apache.commons.jcs.engine.memory.util.MemoryElementDescriptor;
 import org.apache.commons.jcs.engine.stats.behavior.IStats;
@@ -83,124 +78,37 @@
     }
 
     /**
-     * Get an item from the cache
-     * <p>
-     * @param key Identifies item to find
-     * @return ICacheElement&lt;K, V&gt; if found, else null
-     * @throws IOException
+     * Update control structures after get
+     * (guarded by the lock)
+     *
+     * @param me the memory element descriptor
      */
     @Override
-    public ICacheElement<K, V> get( K key )
-        throws IOException
+    protected void lockedGetElement(MemoryElementDescriptor<K, V> me)
     {
-        if ( log.isDebugEnabled() )
-        {
-            log.debug( "getting item from cache " + getCacheName() + " for key " + key );
-        }
-
-        MemoryElementDescriptor<K, V> me = map.get( key );
-
-        if ( me != null )
-        {
-            hitCnt.incrementAndGet();
-            if ( log.isDebugEnabled() )
-            {
-                log.debug( getCacheName() + ": LHMLRUMemoryCache hit for " + key );
-            }
-            return me.getCacheElement();
-        }
-        else
-        {
-            missCnt.incrementAndGet();
-            if ( log.isDebugEnabled() )
-            {
-                log.debug( getCacheName() + ": LHMLRUMemoryCache miss for " + key );
-            }
-        }
-
-        return null;
+        // empty
     }
 
     /**
-     * Removes an item from the cache. This method handles hierarchical removal. If the key is a
-     * String and ends with the CacheConstants.NAME_COMPONENT_DELIMITER, then all items with keys
-     * starting with the argument String will be removed.
-     * <p>
-     * @param key
-     * @return true if removed
-     * @throws IOException
+     * Remove element from control structure
+     * (guarded by the lock)
+     *
+     * @param me the memory element descriptor
      */
     @Override
-    public boolean remove( K key )
-        throws IOException
+    protected void lockedRemoveElement(MemoryElementDescriptor<K, V> me)
     {
-        if ( log.isDebugEnabled() )
-        {
-            log.debug( "removing item for key: " + key );
-        }
-
-        boolean removed = false;
-
-        // handle partial removal
-        if ( key instanceof String && ( (String) key ).endsWith( CacheConstants.NAME_COMPONENT_DELIMITER ) )
-        {
-            // remove all keys of the same name hierarchy.
-            synchronized ( map )
-            {
-                for (Iterator<Map.Entry<K, MemoryElementDescriptor<K, V>>> itr = map.entrySet().iterator(); itr.hasNext(); )
-                {
-                    Map.Entry<K, MemoryElementDescriptor<K, V>> entry = itr.next();
-                    K k = entry.getKey();
-
-                    if ( k instanceof String && ( (String) k ).startsWith( key.toString() ) )
-                    {
-                        itr.remove();
-                        removed = true;
-                    }
-                }
-            }
-        }
-        else if ( key instanceof GroupAttrName && ((GroupAttrName<?>)key).attrName == null )
-        {
-            // remove all keys of the same name hierarchy.
-            synchronized ( map )
-            {
-                for (Iterator<Map.Entry<K, MemoryElementDescriptor<K, V>>> itr = map.entrySet().iterator(); itr.hasNext(); )
-                {
-                    Map.Entry<K, MemoryElementDescriptor<K, V>> entry = itr.next();
-                    K k = entry.getKey();
-
-                    if ( k instanceof GroupAttrName &&
-                        ((GroupAttrName<?>)k).groupId.equals(((GroupAttrName<?>)key).groupId) )
-                    {
-                        itr.remove();
-                        removed = true;
-                    }
-                }
-            }
-        }
-        else
-        {
-            // remove single item.
-            MemoryElementDescriptor<K, V> me = map.remove( key );
-            if ( me != null )
-            {
-                removed = true;
-            }
-        }
-
-        return removed;
+        // empty
     }
 
     /**
-     * Get an Array of the keys for all elements in the memory cache
-     * <p>
-     * @return An Object[]
+     * Removes all cached items from the cache control structures.
+     * (guarded by the lock)
      */
     @Override
-    public Set<K> getKeySet()
+    protected void lockedRemoveAll()
     {
-        return new LinkedHashSet<K>(map.keySet());
+        // empty
     }
 
     /**
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/SoftReferenceMemoryCache.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/SoftReferenceMemoryCache.java
index 5108c66..b5c703b 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/SoftReferenceMemoryCache.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/SoftReferenceMemoryCache.java
@@ -22,7 +22,6 @@
 import java.io.IOException;
 import java.lang.ref.SoftReference;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -30,11 +29,9 @@
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.LinkedBlockingQueue;
 
-import org.apache.commons.jcs.engine.CacheConstants;
 import org.apache.commons.jcs.engine.behavior.ICacheElement;
 import org.apache.commons.jcs.engine.behavior.ICompositeCacheAttributes;
 import org.apache.commons.jcs.engine.control.CompositeCache;
-import org.apache.commons.jcs.engine.control.group.GroupAttrName;
 import org.apache.commons.jcs.engine.memory.AbstractMemoryCache;
 import org.apache.commons.jcs.engine.memory.util.MemoryElementDescriptor;
 import org.apache.commons.jcs.engine.memory.util.SoftReferenceElementDescriptor;
@@ -147,107 +144,41 @@
     }
 
     /**
-     * Removes an item from the cache. This method handles hierarchical removal. If the key is a
-     * String and ends with the CacheConstants.NAME_COMPONENT_DELIMITER, then all items with keys
-     * starting with the argument String will be removed.
-     * <p>
+     * Update control structures after get
+     * (guarded by the lock)
      *
-     * @param key
-     * @return true if the removal was successful
-     * @throws IOException
+     * @param me the memory element descriptor
      */
     @Override
-    public boolean remove(K key) throws IOException
+    protected void lockedGetElement(MemoryElementDescriptor<K, V> me)
     {
-        if (log.isDebugEnabled())
-        {
-            log.debug("removing item for key: " + key);
-        }
+        ICacheElement<K, V> val = me.getCacheElement();
+        val.getElementAttributes().setLastAccessTimeNow();
 
-        boolean removed = false;
-
-        // handle partial removal
-        if (key instanceof String && ((String) key).endsWith(CacheConstants.NAME_COMPONENT_DELIMITER))
-        {
-            // remove all keys of the same name hierarchy.
-            for (Iterator<Map.Entry<K, MemoryElementDescriptor<K, V>>> itr = map.entrySet().iterator();
-                    itr.hasNext();)
-            {
-                Map.Entry<K, MemoryElementDescriptor<K, V>> entry = itr.next();
-                K k = entry.getKey();
-
-                if (k instanceof String && ((String) k).startsWith(key.toString()))
-                {
-                    lock.lock();
-                    try
-                    {
-                        strongReferences.remove(entry.getValue().getCacheElement());
-                        itr.remove();
-                        removed = true;
-                    }
-                    finally
-                    {
-                        lock.unlock();
-                    }
-                }
-            }
-        }
-        else if (key instanceof GroupAttrName && ((GroupAttrName<?>) key).attrName == null)
-        {
-            // remove all keys of the same name hierarchy.
-            for (Iterator<Map.Entry<K, MemoryElementDescriptor<K, V>>> itr = map.entrySet().iterator();
-                    itr.hasNext();)
-            {
-                Map.Entry<K, MemoryElementDescriptor<K, V>> entry = itr.next();
-                K k = entry.getKey();
-
-                if (k instanceof GroupAttrName && ((GroupAttrName<?>) k).groupId.equals(((GroupAttrName<?>) key).groupId))
-                {
-                    lock.lock();
-                    try
-                    {
-                        strongReferences.remove(entry.getValue().getCacheElement());
-                        itr.remove();
-                        removed = true;
-                    }
-                    finally
-                    {
-                        lock.unlock();
-                    }
-                }
-            }
-        }
-        else
-        {
-            // remove single item.
-            lock.lock();
-            try
-            {
-                MemoryElementDescriptor<K, V> me = map.remove(key);
-                if (me != null)
-                {
-                    strongReferences.remove(me.getCacheElement());
-                    removed = true;
-                }
-            }
-            finally
-            {
-                lock.unlock();
-            }
-        }
-
-        return removed;
+        // update the ordering of the strong references
+        strongReferences.add(val);
+        trimStrongReferences();
     }
 
     /**
-     * Removes all cached items from the cache.
-     * <p>
-     * @throws IOException
+     * Remove element from control structure
+     * (guarded by the lock)
+     *
+     * @param me the memory element descriptor
      */
     @Override
-    public void removeAll() throws IOException
+    protected void lockedRemoveElement(MemoryElementDescriptor<K, V> me)
     {
-        super.removeAll();
+        strongReferences.remove(me.getCacheElement());
+    }
+
+    /**
+     * Removes all cached items from the cache control structures.
+     * (guarded by the lock)
+     */
+    @Override
+    protected void lockedRemoveAll()
+    {
         strongReferences.clear();
     }
 
@@ -294,48 +225,6 @@
     }
 
     /**
-     * Get an item from the cache
-     * <p>
-     * @param key Description of the Parameter
-     * @return Description of the Return Value
-     * @throws IOException Description of the Exception
-     */
-    @Override
-    public ICacheElement<K, V> get(K key) throws IOException
-    {
-        ICacheElement<K, V> val = null;
-        lock.lock();
-
-        try
-        {
-            val = getQuiet(key);
-            if (val != null)
-            {
-                val.getElementAttributes().setLastAccessTimeNow();
-
-                // update the ordering of the strong references
-                strongReferences.add(val);
-                trimStrongReferences();
-            }
-        }
-        finally
-        {
-            lock.unlock();
-        }
-
-        if (val == null)
-        {
-            missCnt.incrementAndGet();
-        }
-        else
-        {
-            hitCnt.incrementAndGet();
-        }
-
-        return val;
-    }
-
-    /**
      * This can't be implemented.
      * <p>
      * @param numberToFree
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryReceiver.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryReceiver.java
index e8f9cba..07a6687 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryReceiver.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryReceiver.java
@@ -25,14 +25,15 @@
 import java.net.DatagramPacket;
 import java.net.InetAddress;
 import java.net.MulticastSocket;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.ExecutorService;
 
 import org.apache.commons.jcs.engine.CacheInfo;
 import org.apache.commons.jcs.engine.behavior.IShutdownObserver;
 import org.apache.commons.jcs.io.ObjectInputStreamClassLoaderAware;
 import org.apache.commons.jcs.utils.discovery.UDPDiscoveryMessage.BroadcastType;
-import org.apache.commons.jcs.utils.threadpool.DaemonThreadFactory;
+import org.apache.commons.jcs.utils.threadpool.PoolConfiguration;
+import org.apache.commons.jcs.utils.threadpool.PoolConfiguration.WhenBlockedPolicy;
+import org.apache.commons.jcs.utils.threadpool.ThreadPoolManager;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -56,7 +57,7 @@
     private static final int maxPoolSize = 2;
 
     /** The processor */
-    private ThreadPoolExecutor pooledExecutor = null;
+    private ExecutorService pooledExecutor = null;
 
     /** number of messages received. For debugging and testing. */
     private int cnt = 0;
@@ -91,10 +92,9 @@
         this.multicastPort = multicastPort;
 
         // create a small thread pool to handle a barrage
-        pooledExecutor = (ThreadPoolExecutor)Executors.newFixedThreadPool(maxPoolSize,
-                new DaemonThreadFactory("JCS-UDPDiscoveryReceiver-", Thread.MIN_PRIORITY));
-        pooledExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
-        //pooledExecutor.setMinimumPoolSize(1);
+        pooledExecutor = ThreadPoolManager.getInstance().createPool(
+        		new PoolConfiguration(false, 0, maxPoolSize, maxPoolSize, 0, WhenBlockedPolicy.DISCARDOLDEST, maxPoolSize), 
+        		"JCS-UDPDiscoveryReceiver-", Thread.MIN_PRIORITY);
 
         if ( log.isInfoEnabled() )
         {
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/struct/AbstractLRUMap.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/struct/AbstractLRUMap.java
index c747f4c..9effd97 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/struct/AbstractLRUMap.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/struct/AbstractLRUMap.java
@@ -64,22 +64,20 @@
     private final DoubleLinkedList<LRUElementDescriptor<K, V>> list;
 
     /** Map where items are stored by key. */
-    private Map<K, LRUElementDescriptor<K, V>> map;
+    private final Map<K, LRUElementDescriptor<K, V>> map;
 
-    /** stats */
-    int hitCnt = 0;
-
-    /** stats */
-    int missCnt = 0;
-
-    /** stats */
-    int putCnt = 0;
-
-    /** make configurable */
-    private int chunkSize = 1;
-
+    /** lock to keep map and list synchronous */
     private final Lock lock = new ReentrantLock();
 
+    /** stats */
+    private long hitCnt = 0;
+
+    /** stats */
+    private long missCnt = 0;
+
+    /** stats */
+    private long putCnt = 0;
+
     /**
      * This creates an unbounded version. Setting the max objects will result in spooling on
      * subsequent puts.
@@ -196,7 +194,7 @@
     @Override
     public V get( Object key )
     {
-        V retVal = null;
+        V retVal;
 
         if ( log.isDebugEnabled() )
         {
@@ -205,22 +203,28 @@
 
         LRUElementDescriptor<K, V> me = map.get( key );
 
-        if ( me != null )
+        if ( me == null )
         {
-            hitCnt++;
-            if ( log.isDebugEnabled() )
-            {
-                log.debug( "LRUMap hit for " + key );
-            }
-
-            retVal = me.getPayload();
-
-            list.makeFirst( me );
+            missCnt++;
+            retVal = null;
         }
         else
         {
-            missCnt++;
-            log.debug( "LRUMap miss for " + key );
+            hitCnt++;
+            retVal = me.getPayload();
+            list.makeFirst( me );
+        }
+
+        if ( log.isDebugEnabled() )
+        {
+            if ( me == null )
+            {
+                log.debug( "LRUMap miss for " + key );
+            }
+            else
+            {
+                log.debug( "LRUMap hit for " + key );
+            }
         }
 
         // verifyCache();
@@ -238,20 +242,23 @@
     public V getQuiet( Object key )
     {
         V ce = null;
-
         LRUElementDescriptor<K, V> me = map.get( key );
+
         if ( me != null )
         {
-            if ( log.isDebugEnabled() )
+            ce = me.getPayload();
+        }
+
+        if ( log.isDebugEnabled() )
+        {
+            if ( me == null )
+            {
+                log.debug( "LRUMap quiet miss for " + key );
+            }
+            else
             {
                 log.debug( "LRUMap quiet hit for " + key );
             }
-
-            ce = me.getPayload();
-        }
-        else if ( log.isDebugEnabled() )
-        {
-            log.debug( "LRUMap quiet miss for " + key );
         }
 
         return ce;
@@ -300,17 +307,16 @@
         putCnt++;
 
         LRUElementDescriptor<K, V> old = null;
+        LRUElementDescriptor<K, V> me = new LRUElementDescriptor<K, V>(key, value);
+
         lock.lock();
         try
         {
-            // TODO address double synchronization of addFirst, use write lock
-            addFirst( key, value );
-            // this must be synchronized
-            LRUElementDescriptor<K, V> first = list.getFirst();
-            old = map.put(first.getKey(), first);
+            list.addFirst( me );
+            old = map.put(key, me);
 
             // If the node was the same as an existing node, remove it.
-            if ( old != null && first.getKey().equals(old.getKey()))
+            if ( old != null && key.equals(old.getKey()))
             {
                 list.remove( old );
             }
@@ -321,7 +327,6 @@
         }
 
         // If the element limit is reached, we need to spool
-
         if (shouldRemove())
         {
             if (log.isDebugEnabled())
@@ -332,7 +337,6 @@
             // The spool will put them in a disk event queue, so there is no
             // need to pre-queue the queuing. This would be a bit wasteful
             // and wouldn't save much time in this synchronous call.
-
             while ( shouldRemove() )
             {
                 lock.lock();
@@ -366,10 +370,10 @@
             {
                 log.debug( "update: After spool map size: " + map.size() );
             }
-            if ( map.size() != dumpCacheSize() )
+            if ( map.size() != list.size() )
             {
-                log.error("update: After spool, size mismatch: map.size() = " + map.size() + ", linked list size = "
-                        + dumpCacheSize());
+                log.error("update: After spool, size mismatch: map.size() = " + map.size() +
+                        ", linked list size = " + list.size());
             }
         }
 
@@ -382,37 +386,6 @@
 
     protected abstract boolean shouldRemove();
 
-
-    /**
-     * Adds a new node to the start of the link list.
-     * <p>
-     * @param key
-     * @param val The feature to be added to the First
-     */
-    private void addFirst(K key, V val)
-    {
-        lock.lock();
-        try
-        {
-            LRUElementDescriptor<K, V> me = new LRUElementDescriptor<K, V>(key, val);
-            list.addFirst( me );
-        }
-        finally
-        {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * Returns the size of the list.
-     * <p>
-     * @return int
-     */
-    private int dumpCacheSize()
-    {
-        return list.size();
-    }
-
     /**
      * Dump the cache entries from first to list for debugging.
      */
@@ -458,8 +431,8 @@
         }
 
         boolean found = false;
-        log.debug( "verifycache: mapContains " + map.size() + " elements, linked list contains " + dumpCacheSize()
-            + " elements" );
+        log.debug( "verifycache: mapContains " + map.size() +
+                " elements, linked list contains " + list.size() + " elements" );
         log.debug( "verifycache: checking linked list by key " );
         for (LRUElementDescriptor<K, V> li = list.getFirst(); li != null; li = (LRUElementDescriptor<K, V>) li.next )
         {
@@ -537,37 +510,6 @@
     }
 
     /**
-     * Logs an error is an element that should be in the cache is not.
-     * <p>
-     * @param key
-     */
-    @SuppressWarnings("unchecked") // No generics for public fields
-    protected void verifyCache( Object key )
-    {
-        if ( !log.isDebugEnabled() )
-        {
-            return;
-        }
-
-        boolean found = false;
-
-        // go through the linked list looking for the key
-        for (LRUElementDescriptor<K, V> li = list.getFirst(); li != null; li = (LRUElementDescriptor<K, V>) li.next )
-        {
-            if ( li.getKey() == key )
-            {
-                found = true;
-                log.debug( "verifycache(key) key match: " + key );
-                break;
-            }
-        }
-        if ( !found )
-        {
-            log.error( "verifycache(key), couldn't find key! : " + key );
-        }
-    }
-
-    /**
      * This is called when an item is removed from the LRU. We just log some information.
      * <p>
      * Children can implement this method for special behavior.
@@ -584,24 +526,6 @@
     }
 
     /**
-     * The chunk size is the number of items to remove when the max is reached. By default it is 1.
-     * <p>
-     * @param chunkSize The chunkSize to set.
-     */
-    public void setChunkSize( int chunkSize )
-    {
-        this.chunkSize = chunkSize;
-    }
-
-    /**
-     * @return Returns the chunkSize.
-     */
-    public int getChunkSize()
-    {
-        return chunkSize;
-    }
-
-    /**
      * @return IStats
      */
     public IStats getStatistics()
@@ -613,9 +537,9 @@
 
         elems.add(new StatElement<Integer>( "List Size", Integer.valueOf(list.size()) ) );
         elems.add(new StatElement<Integer>( "Map Size", Integer.valueOf(map.size()) ) );
-        elems.add(new StatElement<Integer>( "Put Count", Integer.valueOf(putCnt) ) );
-        elems.add(new StatElement<Integer>( "Hit Count", Integer.valueOf(hitCnt) ) );
-        elems.add(new StatElement<Integer>( "Miss Count", Integer.valueOf(missCnt) ) );
+        elems.add(new StatElement<Long>( "Put Count", Long.valueOf(putCnt) ) );
+        elems.add(new StatElement<Long>( "Hit Count", Long.valueOf(hitCnt) ) );
+        elems.add(new StatElement<Long>( "Miss Count", Long.valueOf(missCnt) ) );
 
         stats.setStatElements( elems );
 
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/struct/LRUMap.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/struct/LRUMap.java
index fa100b2..84ff231 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/struct/LRUMap.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/struct/LRUMap.java
@@ -19,8 +19,6 @@
  * under the License.
  */
 
-import java.util.concurrent.atomic.AtomicInteger;
-
 /**
  *
  * @author Wiktor Niesiobędzki
@@ -32,10 +30,8 @@
  */
 public class LRUMap<K, V> extends AbstractLRUMap<K, V>
 {
-
     /** if the max is less than 0, there is no limit! */
-    int maxObjects = -1;
-    AtomicInteger counter = new AtomicInteger(0);
+    private int maxObjects = -1;
 
     public LRUMap()
     {
@@ -49,7 +45,7 @@
      */
     public LRUMap(int maxObjects)
     {
-        super();
+        this();
         this.maxObjects = maxObjects;
     }
 
@@ -58,9 +54,4 @@
     {
         return maxObjects > 0 && this.size() > maxObjects;
     }
-
-    public Object getMaxCounter()
-    {
-        return maxObjects;
-    }
 }
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/threadpool/PoolConfiguration.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/threadpool/PoolConfiguration.java
index 05f17e7..f4e886d 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/threadpool/PoolConfiguration.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/threadpool/PoolConfiguration.java
@@ -27,23 +27,46 @@
 public final class PoolConfiguration
     implements Cloneable
 {
+    /**
+     * DEFAULT SETTINGS
+     */
+    private static final boolean DEFAULT_USE_BOUNDARY = true;
+
+    /** Default queue size limit */
+    private static final int DEFAULT_BOUNDARY_SIZE = 2000;
+
+    /** Default max size */
+    private static final int DEFAULT_MAXIMUM_POOL_SIZE = 150;
+
+    /** Default min */
+    private static final int DEFAULT_MINIMUM_POOL_SIZE = Runtime.getRuntime().availableProcessors();
+
+    /** Default keep alive */
+    private static final int DEFAULT_KEEPALIVE_TIME = 1000 * 60 * 5;
+
+    /** Default when blocked */
+    private static final WhenBlockedPolicy DEFAULT_WHEN_BLOCKED_POLICY = WhenBlockedPolicy.RUN;
+
+    /** Default startup size */
+    private static final int DEFAULT_STARTUP_SIZE = DEFAULT_MINIMUM_POOL_SIZE;
+
     /** Should we bound the queue */
-    private boolean useBoundary = true;
+    private boolean useBoundary = DEFAULT_USE_BOUNDARY;
 
     /** If the queue is bounded, how big can it get */
-    private int boundarySize = 2000;
+    private int boundarySize = DEFAULT_BOUNDARY_SIZE;
 
     /** only has meaning if a boundary is used */
-    private int maximumPoolSize = 150;
+    private int maximumPoolSize = DEFAULT_MAXIMUM_POOL_SIZE;
 
     /**
      * the exact number that will be used in a boundless queue. If the queue has a boundary, more
      * will be created if the queue fills.
      */
-    private int minimumPoolSize = 4;
+    private int minimumPoolSize = DEFAULT_MINIMUM_POOL_SIZE;
 
     /** How long idle threads above the minimum should be kept alive. */
-    private int keepAliveTime = 1000 * 60 * 5;
+    private int keepAliveTime = DEFAULT_KEEPALIVE_TIME;
 
     public enum WhenBlockedPolicy {
         /** abort when queue is full and max threads is reached. */
@@ -63,10 +86,10 @@
     }
 
     /** should be ABORT, BLOCK, RUN, WAIT, DISCARDOLDEST, */
-    private WhenBlockedPolicy whenBlockedPolicy = WhenBlockedPolicy.RUN;
+    private WhenBlockedPolicy whenBlockedPolicy = DEFAULT_WHEN_BLOCKED_POLICY;
 
     /** The number of threads to create on startup */
-    private int startUpSize = 4;
+    private int startUpSize = DEFAULT_MINIMUM_POOL_SIZE;
 
     /**
      * @param useBoundary The useBoundary to set.
@@ -89,7 +112,9 @@
      */
     public PoolConfiguration()
     {
-        // nop
+        this( DEFAULT_USE_BOUNDARY, DEFAULT_BOUNDARY_SIZE, DEFAULT_MAXIMUM_POOL_SIZE,
+              DEFAULT_MINIMUM_POOL_SIZE, DEFAULT_KEEPALIVE_TIME,
+              DEFAULT_WHEN_BLOCKED_POLICY, DEFAULT_STARTUP_SIZE );
     }
 
     /**
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/threadpool/ThreadPoolManager.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/threadpool/ThreadPoolManager.java
index 0c9346c..93ca842 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/threadpool/ThreadPoolManager.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/threadpool/ThreadPoolManager.java
@@ -23,11 +23,14 @@
 import java.util.Properties;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.commons.jcs.utils.threadpool.PoolConfiguration.WhenBlockedPolicy;
+import org.apache.commons.jcs.utils.config.PropertySetter;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -39,30 +42,12 @@
  * This manager forces you to use a bounded queue. By default it uses the current thread for
  * execution when the buffer is full and no free threads can be created.
  * <p>
- * You can specify the props file to use or pass in a properties object prior to configuration. By
- * default it looks for configuration information in thread_pool.properties.
+ * You can specify the props file to use or pass in a properties object prior to configuration.
  * <p>
  * If set, the Properties object will take precedence.
  * <p>
- * If a value is not set for a particular pool, the hard coded defaults will be used.
- *
- * <pre>
- * int boundarySize_DEFAULT = 2000;
- *
- * int maximumPoolSize_DEFAULT = 150;
- *
- * int minimumPoolSize_DEFAULT = 4;
- *
- * int keepAliveTime_DEFAULT = 1000 * 60 * 5;
- *
- * boolean abortWhenBlocked = false;
- *
- * String whenBlockedPolicy_DEFAULT = IPoolConfiguration.POLICY_RUN;
- *
- * int startUpSize_DEFAULT = 4;
- * </pre>
- *
- * You can configure default settings by specifying a default pool in the properties, ie "cache.ccf"
+ * If a value is not set for a particular pool, the hard coded defaults in <code>PoolConfiguration</code> will be used.
+ * You can configure default settings by specifying <code>thread_pool.default</code> in the properties, ie "cache.ccf"
  * <p>
  * @author Aaron Smuts
  */
@@ -71,31 +56,8 @@
     /** The logger */
     private static final Log log = LogFactory.getLog( ThreadPoolManager.class );
 
-    /**
-     * DEFAULT SETTINGS, these are not final since they can be set via the properties file or object
-     */
-    private static boolean useBoundary_DEFAULT = true;
-
-    /** Default queue size limit */
-    private static int boundarySize_DEFAULT = 2000;
-
-    /** Default max size */
-    private static int maximumPoolSize_DEFAULT = 150;
-
-    /** Default min */
-    private static int minimumPoolSize_DEFAULT = 4;
-
-    /** Default keep alive */
-    private static int keepAliveTime_DEFAULT = 1000 * 60 * 5;
-
-    /** Default when blocked */
-    private static WhenBlockedPolicy whenBlockedPolicy_DEFAULT = WhenBlockedPolicy.RUN;
-
-    /** Default startup size */
-    private static int startUpSize_DEFAULT = 4;
-
     /** The default config, created using property defaults if present, else those above. */
-    private static PoolConfiguration defaultConfig;
+    private PoolConfiguration defaultConfig;
 
     /** the root property name */
     private static final String PROP_NAME_ROOT = "thread_pool";
@@ -103,7 +65,13 @@
     /** default property file name */
     private static final String DEFAULT_PROP_NAME_ROOT = "thread_pool.default";
 
-    /**
+    /** the scheduler root property name */
+    private static final String PROP_NAME_SCHEDULER_ROOT = "scheduler_pool";
+
+    /** default scheduler property file name */
+    private static final String DEFAULT_PROP_NAME_SCHEDULER_ROOT = "scheduler_pool.default";
+
+   /**
      * You can specify the properties to be used to configure the thread pool. Setting this post
      * initialization will have no effect.
      */
@@ -113,24 +81,42 @@
     private static ThreadPoolManager INSTANCE = null;
 
     /** Map of names to pools. */
-    private ConcurrentHashMap<String, ThreadPoolExecutor> pools;
+    private ConcurrentHashMap<String, ExecutorService> pools;
+
+    /** Map of names to scheduler pools. */
+    private ConcurrentHashMap<String, ScheduledExecutorService> schedulerPools;
 
     /**
      * No instances please. This is a singleton.
      */
     private ThreadPoolManager()
     {
-        this.pools = new ConcurrentHashMap<String, ThreadPoolExecutor>();
+        this.pools = new ConcurrentHashMap<String, ExecutorService>();
+        this.schedulerPools = new ConcurrentHashMap<String, ScheduledExecutorService>();
         configure();
     }
 
     /**
      * Creates a pool based on the configuration info.
      * <p>
-     * @param config
-     * @return A ThreadPoll wrapper
+     * @param config the pool configuration
+     * @param threadNamePrefix prefix for the thread names of the pool
+     * @return A ThreadPool wrapper
      */
-    private ThreadPoolExecutor createPool( PoolConfiguration config )
+    public ExecutorService createPool( PoolConfiguration config, String threadNamePrefix)
+    {
+    	return createPool(config, threadNamePrefix, Thread.NORM_PRIORITY);
+    }
+    
+    /**
+     * Creates a pool based on the configuration info.
+     * <p>
+     * @param config the pool configuration
+     * @param threadNamePrefix prefix for the thread names of the pool
+     * @param threadPriority the priority of the created threads
+     * @return A ThreadPool wrapper
+     */
+    public ExecutorService createPool( PoolConfiguration config, String threadNamePrefix, int threadPriority )
     {
         BlockingQueue<Runnable> queue = null;
         if ( config.isUseBoundary() )
@@ -157,7 +143,7 @@
             config.getKeepAliveTime(),
             TimeUnit.MILLISECONDS,
             queue,
-            new DaemonThreadFactory("JCS-ThreadPoolManager-"));
+            new DaemonThreadFactory(threadNamePrefix, threadPriority));
 
         // when blocked policy
         switch (config.getWhenBlockedPolicy())
@@ -187,6 +173,23 @@
     }
 
     /**
+     * Creates a scheduler pool based on the configuration info.
+     * <p>
+     * @param config the pool configuration
+     * @param threadNamePrefix prefix for the thread names of the pool
+     * @param threadPriority the priority of the created threads
+     * @return A ScheduledExecutorService
+     */
+    public ScheduledExecutorService createSchedulerPool( PoolConfiguration config, String threadNamePrefix, int threadPriority )
+    {
+    	ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(
+    			config.getMaximumPoolSize(), 
+    			new DaemonThreadFactory(threadNamePrefix, threadPriority));
+
+        return scheduler;
+    }
+    
+    /**
      * Returns a configured instance of the ThreadPoolManger To specify a configuration file or
      * Properties object to use call the appropriate setter prior to calling getInstance.
      * <p>
@@ -208,34 +211,46 @@
     {
         if ( INSTANCE != null )
         {
-            for ( String poolName : INSTANCE.getPoolNames())
+            for ( ExecutorService pool : INSTANCE.pools.values() )
             {
                 try
                 {
-                    INSTANCE.getPool(poolName).shutdownNow();
+                    pool.shutdownNow();
                 }
                 catch (Throwable t)
                 {
-                    log.warn("Failed to close pool " + poolName, t);
+                    log.warn("Failed to close pool " + pool, t);
                 }
             }
-
+            
+            for ( ScheduledExecutorService pool : INSTANCE.schedulerPools.values() )
+            {
+                try
+                {
+                    pool.shutdownNow();
+                }
+                catch (Throwable t)
+                {
+                    log.warn("Failed to close pool " + pool, t);
+                }
+            }
+            
             INSTANCE = null;
         }
     }
 
     /**
-     * Returns a pool by name. If a pool by this name does not exist in the configuration file or
+     * Returns an executor service by name. If a service by this name does not exist in the configuration file or
      * properties, one will be created using the default values.
      * <p>
-     * Pools are lazily created.
+     * Services are lazily created.
      * <p>
      * @param name
-     * @return The thread pool configured for the name.
+     * @return The executor service configured for the name.
      */
-    public ThreadPoolExecutor getPool( String name )
+    public ExecutorService getExecutorService( String name )
     {
-        ThreadPoolExecutor pool = pools.get( name );
+    	ExecutorService pool = pools.get( name );
 
         if ( pool == null )
         {
@@ -245,12 +260,17 @@
             }
 
             PoolConfiguration config = loadConfig( PROP_NAME_ROOT + "." + name );
-            pool = createPool( config );
-            ThreadPoolExecutor _pool = pools.putIfAbsent( name, pool );
-            if (_pool != null)
+            ExecutorService _pool = createPool( config, "JCS-ThreadPoolManager-" + name + "-" );
+            pool = pools.putIfAbsent( name, _pool );
+            if (pool == null)
             {
                 pool = _pool;
             }
+            else
+            {
+            	// already created in another thread
+            	_pool.shutdownNow();
+            }
 
             if ( log.isDebugEnabled() )
             {
@@ -260,6 +280,61 @@
 
         return pool;
     }
+    
+    /**
+     * Returns a pool by name. If a pool by this name does not exist in the configuration file or
+     * properties, one will be created using the default values.
+     * <p>
+     * Pools are lazily created.
+     * <p>
+     * @param name
+     * @return The thread pool configured for the name.
+     * 
+     * @deprecated Use getExecutorService() instead
+     */
+    @Deprecated
+	public ThreadPoolExecutor getPool( String name )
+    {
+    	return (ThreadPoolExecutor) getExecutorService(name);
+    }
+
+    /**
+     * Returns a scheduler pool by name. If a pool by this name does not exist in the configuration file or
+     * properties, one will be created using the default values.
+     * <p>
+     * Pools are lazily created.
+     * <p>
+     * @param name
+     * @return The scheduler pool configured for the name.
+     */
+    public ScheduledExecutorService getSchedulerPool( String name )
+    {
+    	ScheduledExecutorService pool = schedulerPools.get( name );
+
+        if ( pool == null )
+        {
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( "Creating scheduler pool for name [" + name + "]" );
+            }
+
+            PoolConfiguration defaultSchedulerConfig = loadConfig( DEFAULT_PROP_NAME_SCHEDULER_ROOT );
+            PoolConfiguration config = loadConfig( PROP_NAME_SCHEDULER_ROOT + "." + name, defaultSchedulerConfig );
+            ScheduledExecutorService _pool = createSchedulerPool( config, "JCS-ThreadPoolManager-" + name + "-", Thread.NORM_PRIORITY );
+            pool = schedulerPools.putIfAbsent( name, _pool );
+            if (pool == null)
+            {
+                pool = _pool;
+            }
+            else
+            {
+            	// already created in another thread
+            	_pool.shutdownNow();
+            }
+        }
+
+        return pool;
+    }
 
     /**
      * Returns the names of all configured pools.
@@ -285,7 +360,7 @@
     /**
      * Initialize the ThreadPoolManager and create all the pools defined in the configuration.
      */
-    private static void configure()
+    private void configure()
     {
         if ( log.isDebugEnabled() )
         {
@@ -300,88 +375,36 @@
 
         // set intial default and then override if new
         // settings are available
-        defaultConfig = new PoolConfiguration( useBoundary_DEFAULT, boundarySize_DEFAULT, maximumPoolSize_DEFAULT,
-                                               minimumPoolSize_DEFAULT, keepAliveTime_DEFAULT,
-                                               whenBlockedPolicy_DEFAULT, startUpSize_DEFAULT );
-
+        defaultConfig = new PoolConfiguration();
         defaultConfig = loadConfig( DEFAULT_PROP_NAME_ROOT );
     }
 
     /**
-     * Configures the default PoolConfiguration settings.
+     * Configures the PoolConfiguration settings.
      * <p>
-     * @param root
+     * @param root the configuration key prefix
      * @return PoolConfiguration
      */
-    private static PoolConfiguration loadConfig( String root )
+    private PoolConfiguration loadConfig( String root )
     {
-        PoolConfiguration config = defaultConfig.clone();
+    	return loadConfig(root, defaultConfig);
+    }
+    
+    /**
+     * Configures the PoolConfiguration settings.
+     * <p>
+     * @param root the configuration key prefix
+     * @param defaultPoolConfiguration the default configuration
+     * @return PoolConfiguration
+     */
+    private PoolConfiguration loadConfig( String root, PoolConfiguration defaultPoolConfiguration )
+    {
+        PoolConfiguration config = defaultPoolConfiguration.clone();
+        PropertySetter.setProperties( config, props, root + "." );
 
-        try
+        if ( log.isDebugEnabled() )
         {
-            config.setUseBoundary( Boolean.parseBoolean( props.getProperty( root + ".useBoundary", "false" ) ) );
-        }
-        catch ( NumberFormatException nfe )
-        {
-            log.error( "useBoundary not a boolean.", nfe );
-        }
-
-        // load default if they exist
-        try
-        {
-            config.setBoundarySize( Integer.parseInt( props.getProperty( root + ".boundarySize", "2000" ) ) );
-        }
-        catch ( NumberFormatException nfe )
-        {
-            log.error( "boundarySize not a number.", nfe );
-        }
-
-        // maximum pool size
-        try
-        {
-            config.setMaximumPoolSize( Integer.parseInt( props.getProperty( root + ".maximumPoolSize", "150" ) ) );
-        }
-        catch ( NumberFormatException nfe )
-        {
-            log.error( "maximumPoolSize not a number.", nfe );
-        }
-
-        // minimum pool size
-        try
-        {
-            config.setMinimumPoolSize( Integer.parseInt( props.getProperty( root + ".minimumPoolSize", "4" ) ) );
-        }
-        catch ( NumberFormatException nfe )
-        {
-            log.error( "minimumPoolSize not a number.", nfe );
-        }
-
-        // keep alive
-        try
-        {
-            config.setKeepAliveTime( Integer.parseInt( props.getProperty( root + ".keepAliveTime", "300000" ) ) );
-        }
-        catch ( NumberFormatException nfe )
-        {
-            log.error( "keepAliveTime not a number.", nfe );
-        }
-
-        // when blocked
-        config.setWhenBlockedPolicy( props.getProperty( root + ".whenBlockedPolicy", "RUN" ) );
-
-        // startupsize
-        try
-        {
-            config.setStartUpSize( Integer.parseInt( props.getProperty( root + ".startUpSize", "4" ) ) );
-        }
-        catch ( NumberFormatException nfe )
-        {
-            log.error( "startUpSize not a number.", nfe );
-        }
-
-        if ( log.isInfoEnabled() )
-        {
-            log.info( root + " PoolConfiguration = " + config );
+            log.debug( root + " PoolConfiguration = " + config );
         }
 
         return config;
diff --git a/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/indexed/IndexedDiskCacheOptimizationUnitTest.java b/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/indexed/IndexedDiskCacheOptimizationUnitTest.java
index 77df909..8317505 100644
--- a/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/indexed/IndexedDiskCacheOptimizationUnitTest.java
+++ b/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/indexed/IndexedDiskCacheOptimizationUnitTest.java
@@ -65,8 +65,8 @@
 
         Thread.sleep( 1000 );
         long sizeBeforeRemove = disk.getDataFileSize();
-        System.out.println( "file sizeBeforeRemove " + sizeBeforeRemove );
-        System.out.println( "totalSize inserted " + DiskTestObjectUtil.totalSize( elements, numberToInsert ) );
+        // System.out.println( "file sizeBeforeRemove " + sizeBeforeRemove );
+        // System.out.println( "totalSize inserted " + DiskTestObjectUtil.totalSize( elements, numberToInsert ) );
 
         // DO WORK
         for ( int i = 0; i < removeCount; i++ )
diff --git a/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/remote/RemoteCacheNoWaitUnitTest.java b/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/remote/RemoteCacheNoWaitUnitTest.java
index fe671ae..231841a 100644
--- a/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/remote/RemoteCacheNoWaitUnitTest.java
+++ b/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/remote/RemoteCacheNoWaitUnitTest.java
@@ -1,5 +1,16 @@
 package org.apache.commons.jcs.auxiliary.remote;
 
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.jcs.engine.CacheElement;
+import org.apache.commons.jcs.engine.CacheStatus;
+import org.apache.commons.jcs.engine.behavior.ICacheElement;
+import org.apache.commons.jcs.engine.behavior.ICacheEventQueue;
+import org.apache.commons.jcs.utils.timing.SleepUtil;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -20,16 +31,6 @@
  */
 
 import junit.framework.TestCase;
-import org.apache.commons.jcs.engine.CacheElement;
-import org.apache.commons.jcs.engine.CacheStatus;
-import org.apache.commons.jcs.engine.behavior.ICacheElement;
-import org.apache.commons.jcs.engine.behavior.ICacheEventQueue;
-import org.apache.commons.jcs.utils.timing.SleepUtil;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
 
 /**
  * Unit tests for the remote cache no wait. The no wait manages a queue on top of the client.
@@ -198,7 +199,7 @@
         // DO WORK
         noWait.update( element );
         SleepUtil.sleepAtLeast( 10 );
-        ICacheEventQueue<String, String> originalQueue = noWait.getCacheEventQueue();
+        // ICacheEventQueue<String, String> originalQueue = noWait.getCacheEventQueue();
 
         noWait.fixCache( service );
 
@@ -208,7 +209,7 @@
 
         // VERIFY
         assertEquals( "Wrong status", service, client.fixed );
-        assertFalse( "Original queue should not alive", originalQueue.isAlive() );
+        // assertFalse( "Original queue should not alive", originalQueue.isAlive() );
         assertTrue( "New queue should be alive." + newQueue, newQueue.isAlive() );
     }
 }
diff --git a/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/CacheEventQueueFactoryUnitTest.java b/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/CacheEventQueueFactoryUnitTest.java
index 3925b63..60b72f3 100644
--- a/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/CacheEventQueueFactoryUnitTest.java
+++ b/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/CacheEventQueueFactoryUnitTest.java
@@ -1,5 +1,10 @@
 package org.apache.commons.jcs.engine;
 
+import org.apache.commons.jcs.auxiliary.remote.MockRemoteCacheListener;
+import org.apache.commons.jcs.engine.behavior.ICacheEventQueue;
+import org.apache.commons.jcs.engine.behavior.ICacheEventQueue.QueueType;
+import org.apache.commons.jcs.engine.behavior.ICacheListener;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -20,10 +25,6 @@
  */
 
 import junit.framework.TestCase;
-import org.apache.commons.jcs.auxiliary.remote.MockRemoteCacheListener;
-import org.apache.commons.jcs.engine.behavior.ICacheEventQueue;
-import org.apache.commons.jcs.engine.behavior.ICacheEventQueue.QueueType;
-import org.apache.commons.jcs.engine.behavior.ICacheListener;
 
 /** Unit tests for the CacheEventQueueFactory */
 public class CacheEventQueueFactoryUnitTest
@@ -44,7 +45,7 @@
 
         // VERIFY
         assertNotNull( "Should have a result", result );
-        assertTrue( "Wrong type", result instanceof CacheEventQueue );
+        assertTrue( "Wrong type", result.getQueueType() == QueueType.SINGLE );
     }
 
     /** Test create */
@@ -62,6 +63,6 @@
 
         // VERIFY
         assertNotNull( "Should have a result", result );
-        assertTrue( "Wrong type", result instanceof PooledCacheEventQueue );
+        assertTrue( "Wrong type", result.getQueueType() == QueueType.POOLED );
     }
 }
diff --git a/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/EventQueueConcurrentLoadTest.java b/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/EventQueueConcurrentLoadTest.java
index 8aa4bb8..799ebf4 100644
--- a/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/EventQueueConcurrentLoadTest.java
+++ b/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/EventQueueConcurrentLoadTest.java
@@ -21,13 +21,13 @@
 
 import java.io.IOException;
 
+import org.apache.commons.jcs.engine.behavior.ICacheElement;
+import org.apache.commons.jcs.engine.behavior.ICacheListener;
+
 import junit.extensions.ActiveTestSuite;
 import junit.framework.Test;
 import junit.framework.TestCase;
 
-import org.apache.commons.jcs.engine.behavior.ICacheElement;
-import org.apache.commons.jcs.engine.behavior.ICacheListener;
-
 /**
  * This test case is designed to makes sure there are no deadlocks in the event queue. The time to
  * live should be set to a very short interval to make a deadlock more likely.
@@ -109,16 +109,6 @@
             }
         } );
 
-        suite.addTest( new EventQueueConcurrentLoadTest( "testStopProcessing1" )
-        {
-            @Override
-            public void runTest()
-                throws Exception
-            {
-                this.runStopProcessingTest();
-            }
-        } );
-
         suite.addTest( new EventQueueConcurrentLoadTest( "testRunPutTest4" )
         {
             @Override
@@ -139,16 +129,6 @@
             }
         } );
 
-        suite.addTest( new EventQueueConcurrentLoadTest( "testStopProcessing2" )
-        {
-            @Override
-            public void runTest()
-                throws Exception
-            {
-                this.runStopProcessingTest();
-            }
-        } );
-
         suite.addTest( new EventQueueConcurrentLoadTest( "testRunPutDelayTest" )
         {
             @Override
@@ -222,16 +202,6 @@
     }
 
     /**
-     * Add remove events to the event queue.
-     * @throws Exception
-     */
-    public void runStopProcessingTest()
-        throws Exception
-    {
-        queue.stopProcessing();
-    }
-
-    /**
      * Test putting and a delay. Waits until queue is empty to start.
      * @param end
      * @param expectedPutCount
diff --git a/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/struct/LRUMapConcurrentUnitTest.java b/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/struct/LRUMapConcurrentUnitTest.java
index 09b6005..6ce5625 100644
--- a/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/struct/LRUMapConcurrentUnitTest.java
+++ b/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/struct/LRUMapConcurrentUnitTest.java
@@ -1,5 +1,7 @@
 package org.apache.commons.jcs.utils.struct;
 
+import java.util.Iterator;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -23,8 +25,6 @@
 import junit.framework.TestCase;
 import junit.framework.TestSuite;
 
-import java.util.Iterator;
-
 /**
  * Tests the LRUMap
  *
@@ -150,7 +150,6 @@
     {
         int total = 10;
         LRUMap<String, String> map = new LRUMap<String, String>( total );
-        map.setChunkSize( 1 );
 
         // put the max in
         for ( int i = 0; i < total; i++ )
@@ -189,7 +188,6 @@
     {
         int total = 10000;
         LRUMap<String, String> map = new LRUMap<String, String>( total );
-        map.setChunkSize( 1 );
 
         // put the max in
         for ( int i = 0; i < total * 2; i++ )
@@ -201,7 +199,6 @@
         for ( int i = total - 1; i >= 0; i-- )
         {
             assertNull( map.get( i + ":key" ) );
-
         }
 
         // get the total to total *2 items out, these should be found.
@@ -212,7 +209,6 @@
         }
 
 //        System.out.println( map.getStatistics() );
-
     }
 
     /**
diff --git a/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/struct/LRUMapPerformanceTest.java b/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/struct/LRUMapPerformanceTest.java
index bbf851f..e11d7ab 100644
--- a/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/struct/LRUMapPerformanceTest.java
+++ b/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/struct/LRUMapPerformanceTest.java
@@ -1,5 +1,9 @@
 package org.apache.commons.jcs.utils.struct;
 
+import java.util.Map;
+
+import org.apache.commons.jcs.JCSvsHashtablePerformanceTest;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -22,9 +26,6 @@
 import junit.framework.Test;
 import junit.framework.TestCase;
 import junit.framework.TestSuite;
-import org.apache.commons.jcs.JCSvsHashtablePerformanceTest;
-
-import java.util.Map;
 
 /**
  * This ensures that the jcs version of the LRU map is as fast as the commons
@@ -106,7 +107,7 @@
 
         try
         {
-            Map<String, String> cache = new LRUMap<String, String>( tries );
+            LRUMap<String, String> cache = new LRUMap<String, String>( tries );
 
             for ( int j = 0; j < loops; j++ )
             {
@@ -134,9 +135,12 @@
                 System.out.println( name + " get time for " + tries + " = " + time + "; millis per = " + tPer );
 
                 ///////////////////////////////////////////////////////////////
-                cache2Name = "LRUMapJCS (commons)";
+                cache2Name = "LRUMap (commons)";
                 //or LRUMapJCS
                 Map<String, String> cache2 = new org.apache.commons.collections4.map.LRUMap<String, String>( tries );
+//                Map<String, String> cache2 = new ConcurrentLinkedHashMap.Builder<String, String>()
+//                        .maximumWeightedCapacity( tries )
+//                        .build();
                 //cache2Name = "Hashtable";
                 //Hashtable cache2 = new Hashtable();
                 start = System.currentTimeMillis();
diff --git a/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/threadpool/ThreadPoolManagerUnitTest.java b/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/threadpool/ThreadPoolManagerUnitTest.java
index e2210a1..1c89cc5 100644
--- a/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/threadpool/ThreadPoolManagerUnitTest.java
+++ b/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/threadpool/ThreadPoolManagerUnitTest.java
@@ -21,12 +21,14 @@
 
 import java.util.ArrayList;
 import java.util.Properties;
+import java.util.concurrent.RejectedExecutionHandler;
 import java.util.concurrent.ThreadPoolExecutor;
-
-import junit.framework.TestCase;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.commons.jcs.utils.props.PropertyLoader;
 
+import junit.framework.TestCase;
+
 /**
  * Verify that the manager can create pools as intended by the default and
  * specified file names.
@@ -63,6 +65,39 @@
     }
 
     /**
+     * Make sure it can load a certain configuration
+     */
+    public void testSpecialConfig()
+    {
+        Properties props = PropertyLoader.loadProperties( "thread_pool.properties" );
+        ThreadPoolManager.setProps( props );
+        ThreadPoolManager mgr = ThreadPoolManager.getInstance();
+        assertNotNull( mgr );
+
+        ThreadPoolExecutor pool = mgr.getPool( "aborttest" );
+        assertNotNull( pool );
+
+        int poolSize = pool.getCorePoolSize();
+        int expectedPoolSize = Integer.parseInt( props.getProperty( "thread_pool.aborttest.startUpSize" ) );
+        assertEquals( expectedPoolSize, poolSize);
+
+        int minPoolSize = pool.getPoolSize();
+        int expectedMinPoolSize = Integer.parseInt( props.getProperty( "thread_pool.aborttest.minimumPoolSize" ) );
+        assertEquals( expectedMinPoolSize, minPoolSize );
+
+        int maxPoolSize = pool.getMaximumPoolSize();
+        int expectedMaxPoolSize = Integer.parseInt( props.getProperty( "thread_pool.aborttest.maximumPoolSize" ) );
+        assertEquals( expectedMaxPoolSize, maxPoolSize );
+
+        long keepAliveTime = pool.getKeepAliveTime(TimeUnit.MILLISECONDS);
+        long expectedKeepAliveTime = Long.parseLong( props.getProperty( "thread_pool.aborttest.keepAliveTime" ) );
+        assertEquals( expectedKeepAliveTime, keepAliveTime );
+        
+        RejectedExecutionHandler whenBlockedPolicy = pool.getRejectedExecutionHandler();
+        assertTrue( whenBlockedPolicy instanceof ThreadPoolExecutor.AbortPolicy );
+    }
+    
+    /**
      * Try to get an undefined pool from an existing default file.
      */
     public void testDefaultConfigUndefinedPool()
@@ -91,10 +126,10 @@
         assertNotNull( mgr );
 
         String poolName1 = "testGetPoolNames1";
-        mgr.getPool( poolName1 );
+        mgr.getExecutorService( poolName1 );
 
         String poolName2 = "testGetPoolNames2";
-        mgr.getPool( poolName2 );
+        mgr.getExecutorService( poolName2 );
 
         ArrayList<String> names = mgr.getPoolNames();
         assertTrue( "Should have name in list.", names.contains( poolName1 ) );
diff --git a/commons-jcs-core/src/test/test-conf/thread_pool.properties b/commons-jcs-core/src/test/test-conf/thread_pool.properties
index cbf5284..b6a3326 100644
--- a/commons-jcs-core/src/test/test-conf/thread_pool.properties
+++ b/commons-jcs-core/src/test/test-conf/thread_pool.properties
@@ -44,13 +44,13 @@
 thread_pool.maxtest.whenBlockedPolicy=RUN
 thread_pool.maxtest.startUpSize=5
 
-# wait test thread pool config
-thread_pool.waittest.boundarySize=1
-thread_pool.waittest.maximumPoolSize=11
-thread_pool.waittest.minimumPoolSize=1
-thread_pool.waittest.keepAliveTime=1
-thread_pool.waittest.whenBlockedPolicy=WAIT
-thread_pool.waittest.startUpSize=1
+# abort test thread pool config
+thread_pool.aborttest.boundarySize=1
+thread_pool.aborttest.maximumPoolSize=11
+thread_pool.aborttest.minimumPoolSize=1
+thread_pool.aborttest.keepAliveTime=1
+thread_pool.aborttest.whenBlockedPolicy=ABORT
+thread_pool.aborttest.startUpSize=1
 
 # with boundary test thread pool config
 thread_pool.withbound.useBoundary=true
@@ -58,7 +58,7 @@
 thread_pool.withbound.maximumPoolSize=11
 thread_pool.withbound.minimumPoolSize=1
 thread_pool.withbound.keepAliveTime=1
-thread_pool.withbound.whenBlockedPolicy=WAIT
+thread_pool.withbound.whenBlockedPolicy=ABORT
 thread_pool.withbound.startUpSize=1
 
 
@@ -68,5 +68,5 @@
 thread_pool.nobound.maximumPoolSize=11
 thread_pool.nobound.minimumPoolSize=1
 thread_pool.nobound.keepAliveTime=1
-thread_pool.nobound.whenBlockedPolicy=WAIT
+thread_pool.nobound.whenBlockedPolicy=ABORT
 thread_pool.nobound.startUpSize=1
diff --git a/commons-jcs-dist/pom.xml b/commons-jcs-dist/pom.xml
index 0991542..559b600 100644
--- a/commons-jcs-dist/pom.xml
+++ b/commons-jcs-dist/pom.xml
@@ -32,9 +32,9 @@
   <description>Creates the Apache Commons JCS multimodule distribution.</description>
 
   <scm>
-    <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-dist</connection>
-    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-dist</developerConnection>
-    <url>http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-dist</url>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-dist</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-dist</developerConnection>
+    <url>http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-dist</url>
   </scm>
 
   <!-- NOTE: These dependency declarations are only required to sort this project to the 
diff --git a/commons-jcs-jcache-extras/pom.xml b/commons-jcs-jcache-extras/pom.xml
index 741923f..091cbea 100644
--- a/commons-jcs-jcache-extras/pom.xml
+++ b/commons-jcs-jcache-extras/pom.xml
@@ -30,9 +30,9 @@
   <name>Apache Commons JCS :: JCache Extras</name>
 
   <scm>
-    <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-jcache-extras</connection>
-    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-jcache-extras</developerConnection>
-    <url>http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-jcache-extras</url>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-jcache-extras</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-jcache-extras</developerConnection>
+    <url>http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-jcache-extras</url>
   </scm>
 
   <dependencies>
diff --git a/commons-jcs-jcache-openjpa/pom.xml b/commons-jcs-jcache-openjpa/pom.xml
index b7efa57..a83133b 100644
--- a/commons-jcs-jcache-openjpa/pom.xml
+++ b/commons-jcs-jcache-openjpa/pom.xml
@@ -30,9 +30,9 @@
   <name>Apache Commons JCS :: JCache OpenJPA</name>
 
   <scm>
-    <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-jcache-openjpa</connection>
-    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-jcache-openjpa</developerConnection>
-    <url>http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-jcache-openjpa</url>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-jcache-openjpa</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-jcache-openjpa</developerConnection>
+    <url>http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-jcache-openjpa</url>
   </scm>
 
   <dependencies>
diff --git a/commons-jcs-jcache/pom.xml b/commons-jcs-jcache/pom.xml
index b6fb71e..15d2c8d 100644
--- a/commons-jcs-jcache/pom.xml
+++ b/commons-jcs-jcache/pom.xml
@@ -32,9 +32,9 @@
   <name>Apache Commons JCS :: JCache</name>
 
   <scm>
-    <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-jcache</connection>
-    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-jcache</developerConnection>
-    <url>http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-jcache</url>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-jcache</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-jcache</developerConnection>
+    <url>http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-jcache</url>
   </scm>
 
   <dependencies>
diff --git a/commons-jcs-tck-tests/pom.xml b/commons-jcs-tck-tests/pom.xml
index 4e61e0b..7ecb150 100644
--- a/commons-jcs-tck-tests/pom.xml
+++ b/commons-jcs-tck-tests/pom.xml
@@ -39,9 +39,9 @@
   <name>Apache Commons JCS :: JCache TCK</name>
 
   <scm>
-    <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-tck-tests</connection>
-    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-tck-tests</developerConnection>
-    <url>http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-tck-tests</url>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-tck-tests</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-tck-tests</developerConnection>
+    <url>http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-tck-tests</url>
   </scm>
 
   <properties>
diff --git a/pom.xml b/pom.xml
index 094c6b2..c51c573 100644
--- a/pom.xml
+++ b/pom.xml
@@ -51,9 +51,9 @@
   </issueManagement>
 
   <scm>
-    <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC</connection>
-    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC</developerConnection>
-    <url>http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.1-RC</url>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/trunk</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/trunk</developerConnection>
+    <url>http://svn.apache.org/viewvc/commons/proper/jcs/trunk</url>
   </scm>
 
   <mailingLists>
@@ -519,8 +519,8 @@
     <maven.compiler.target>1.6</maven.compiler.target>
 
     <commons.componentid>jcs</commons.componentid>
-    <commons.release.version>2.1</commons.release.version>
-    <commons.release.name>commons-jcs-dist-2.1</commons.release.name>
+    <commons.release.version>2.0</commons.release.version>
+    <commons.release.name>commons-jcs-dist-2.0</commons.release.name>
     <commons.release.desc>(Java 6.0+)</commons.release.desc>
     <!-- The RC version used in the staging repository URL. -->
     <commons.rc.version>RC1</commons.rc.version>