Cleanup, use ElapsedTimer
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/block/BlockDiskCache.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/block/BlockDiskCache.java
index 90df796..1fd383c 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/block/BlockDiskCache.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/block/BlockDiskCache.java
@@ -35,7 +35,6 @@
 
 import org.apache.commons.jcs.auxiliary.AuxiliaryCacheAttributes;
 import org.apache.commons.jcs.auxiliary.disk.AbstractDiskCache;
-import org.apache.commons.jcs.engine.CacheConstants;
 import org.apache.commons.jcs.engine.behavior.ICacheElement;
 import org.apache.commons.jcs.engine.behavior.IElementSerializer;
 import org.apache.commons.jcs.engine.behavior.IRequireScheduler;
@@ -419,7 +418,7 @@
 
         try
         {
-            if (key instanceof String && key.toString().endsWith(CacheConstants.NAME_COMPONENT_DELIMITER))
+            if (key instanceof String && key.toString().endsWith(NAME_COMPONENT_DELIMITER))
             {
                 removed = performPartialKeyRemoval((String) key);
             }
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/indexed/IndexedDiskCache.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/indexed/IndexedDiskCache.java
index ed4ecf9..68d9eef 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/indexed/IndexedDiskCache.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/indexed/IndexedDiskCache.java
@@ -40,7 +40,6 @@
 import org.apache.commons.jcs.auxiliary.AuxiliaryCacheAttributes;
 import org.apache.commons.jcs.auxiliary.disk.AbstractDiskCache;
 import org.apache.commons.jcs.auxiliary.disk.behavior.IDiskCacheAttributes.DiskLimitType;
-import org.apache.commons.jcs.engine.CacheConstants;
 import org.apache.commons.jcs.engine.behavior.ICacheElement;
 import org.apache.commons.jcs.engine.behavior.IElementSerializer;
 import org.apache.commons.jcs.engine.control.group.GroupAttrName;
@@ -405,7 +404,7 @@
      */
     protected boolean checkForDedOverlaps(IndexedDiskElementDescriptor[] sortedDescriptors)
     {
-        long start = System.currentTimeMillis();
+        ElapsedTimer timer = new ElapsedTimer();
         boolean isOk = true;
         long expectedNextPos = 0;
         for (int i = 0; i < sortedDescriptors.length; i++)
@@ -422,8 +421,8 @@
                 expectedNextPos = ded.pos + IndexedDisk.HEADER_SIZE_BYTES + ded.len;
             }
         }
-        long end = System.currentTimeMillis();
-        log.debug("{0}: Check for DED overlaps took {1} ms.", logCacheName, end - start);
+        log.debug("{0}: Check for DED overlaps took {1} ms.", () -> logCacheName,
+                () -> timer.getElapsedTime());
 
         return isOk;
     }
@@ -730,7 +729,7 @@
         {
             storageLock.writeLock().lock();
 
-            if (key instanceof String && key.toString().endsWith(CacheConstants.NAME_COMPONENT_DELIMITER))
+            if (key instanceof String && key.toString().endsWith(NAME_COMPONENT_DELIMITER))
             {
                 removed = performPartialKeyRemoval((String) key);
             }
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCache.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCache.java
index 2bd7ff2..508eec2 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCache.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCache.java
@@ -36,7 +36,6 @@
 import org.apache.commons.jcs.auxiliary.AuxiliaryCacheAttributes;
 import org.apache.commons.jcs.auxiliary.disk.AbstractDiskCache;
 import org.apache.commons.jcs.auxiliary.disk.jdbc.dsfactory.DataSourceFactory;
-import org.apache.commons.jcs.engine.CacheConstants;
 import org.apache.commons.jcs.engine.behavior.ICacheElement;
 import org.apache.commons.jcs.engine.behavior.ICompositeCacheManager;
 import org.apache.commons.jcs.engine.behavior.IElementSerializer;
@@ -528,7 +527,7 @@
         try (Connection con = getDataSource().getConnection())
         {
             boolean partial = false;
-            if ( key instanceof String && key.toString().endsWith( CacheConstants.NAME_COMPONENT_DELIMITER ) )
+            if ( key instanceof String && key.toString().endsWith( NAME_COMPONENT_DELIMITER ) )
             {
                 // remove all keys of the same name group.
                 sql = "delete from " + getJdbcDiskCacheAttributes().getTableName()
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/ShrinkerThread.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/ShrinkerThread.java
index 24a9580..4e0a5d6 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/ShrinkerThread.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/ShrinkerThread.java
@@ -24,6 +24,7 @@
 
 import org.apache.commons.jcs.log.Log;
 import org.apache.commons.jcs.log.LogManager;
+import org.apache.commons.jcs.utils.timing.ElapsedTimer;
 
 /**
  * Calls delete expired on the disk caches. The shrinker is run by a clock daemon. The shrinker
@@ -100,12 +101,11 @@
         for (Iterator<JDBCDiskCache<?, ?>> i = shrinkSet.iterator(); i.hasNext();)
         {
             JDBCDiskCache<?, ?> cache = i.next();
-            long start = System.currentTimeMillis();
+            ElapsedTimer timer = new ElapsedTimer();
             int deleted = cache.deleteExpired();
-            long end = System.currentTimeMillis();
 
             log.info( "Deleted [{0}] expired for region [{1}] for table [{2}] in {3} ms.",
-                    deleted, cache.getCacheName(), cache.getTableName(), end - start );
+                    deleted, cache.getCacheName(), cache.getTableName(), timer.getElapsedTime() );
 
             // don't pause after the last call to delete expired.
             if ( i.hasNext() )
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLTableOptimizer.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLTableOptimizer.java
index 58a8fd3..585947f 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLTableOptimizer.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLTableOptimizer.java
@@ -29,6 +29,7 @@
 import org.apache.commons.jcs.auxiliary.disk.jdbc.TableState;
 import org.apache.commons.jcs.log.Log;
 import org.apache.commons.jcs.log.LogManager;
+import org.apache.commons.jcs.utils.timing.ElapsedTimer;
 
 /**
  * The MySQL Table Optimizer can optimize MySQL tables. It knows how to optimize for MySQL databases
@@ -115,7 +116,7 @@
      */
     public boolean optimizeTable()
     {
-        long start = System.currentTimeMillis();
+        ElapsedTimer timer = new ElapsedTimer();
         boolean success = false;
 
         if ( tableState.getState() == TableState.OPTIMIZATION_RUNNING )
@@ -185,9 +186,8 @@
         {
             tableState.setState( TableState.FREE );
 
-            long end = System.currentTimeMillis();
             log.info( "Optimization of table [{0}] took {1} ms.",
-                    this.getTableName(), end - start );
+                    () -> this.getTableName(), () -> timer.getElapsedTime() );
         }
 
         return success;
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/server/RemoteCacheServer.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/server/RemoteCacheServer.java
index e391786..4d5f3db 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/server/RemoteCacheServer.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/server/RemoteCacheServer.java
@@ -50,6 +50,7 @@
 import org.apache.commons.jcs.engine.logging.behavior.ICacheEventLogger;
 import org.apache.commons.jcs.log.Log;
 import org.apache.commons.jcs.log.LogManager;
+import org.apache.commons.jcs.utils.timing.ElapsedTimer;
 
 /**
  * This class provides remote cache services. The remote cache server propagates events from local
@@ -78,9 +79,6 @@
     /** log instance */
     private static final Log log = LogManager.getLog( RemoteCacheServer.class );
 
-    /** timing -- if we should record operation times. */
-    private static final boolean timing = true;
-
     /** Number of puts into the cache. */
     private int puts = 0;
 
@@ -264,12 +262,7 @@
      */
     private void processUpdate( ICacheElement<K, V> item, long requesterId )
     {
-        long start = 0;
-        if ( timing )
-        {
-            start = System.currentTimeMillis();
-        }
-
+        ElapsedTimer timer = new ElapsedTimer();
         logUpdateInfo( item );
 
         try
@@ -315,7 +308,7 @@
                         c.update( item );
                     }
                 }
-                catch ( Exception ce )
+                catch ( IOException ce )
                 {
                     // swallow
                     log.info( "Exception caught updating item. requesterId [{0}]: {1}",
@@ -347,11 +340,7 @@
         }
 
         // TODO use JAMON for timing
-        if ( timing )
-        {
-            long end = System.currentTimeMillis();
-            log.debug( "put took {0} ms.", end - start);
-        }
+        log.debug( "put took {0} ms.", () -> timer.getElapsedTime());
     }
 
     /**
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/CacheConstants.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/CacheConstants.java
deleted file mode 100644
index d474af6..0000000
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/CacheConstants.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.apache.commons.jcs.engine;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/**
- * Constants used throughout the JCS cache engine
- * <p>
- * @version $Id$
- */
-public interface CacheConstants
-{
-    /** This is the name of the config file that we will look for by default. */
-    String DEFAULT_CONFIG = "/cache.ccf";
-
-    /** Delimiter of a cache name component. This is used for hierarchical deletion */
-    String NAME_COMPONENT_DELIMITER = ":";
-}
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/behavior/ICache.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/behavior/ICache.java
index dc9d313..1dd0b7f 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/behavior/ICache.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/behavior/ICache.java
@@ -1,5 +1,9 @@
 package org.apache.commons.jcs.engine.behavior;
 
+import java.io.IOException;
+import java.util.Map;
+import java.util.Set;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -22,23 +26,22 @@
 import org.apache.commons.jcs.engine.CacheStatus;
 import org.apache.commons.jcs.engine.match.behavior.IKeyMatcher;
 
-import java.io.IOException;
-import java.util.Map;
-import java.util.Set;
-
 /**
  * This is the top level interface for all cache like structures. It defines the methods used
  * internally by JCS to access, modify, and instrument such structures.
- * 
+ *
  * This allows for a suite of reusable components for accessing such structures, for example
  * asynchronous access via an event queue.
  */
 public interface ICache<K, V>
     extends ICacheType
 {
+    /** Delimiter of a cache name component. This is used for hierarchical deletion */
+    String NAME_COMPONENT_DELIMITER = ":";
+
     /**
      * Puts an item to the cache.
-     * 
+     *
      * @param element
      * @throws IOException
      */
@@ -47,7 +50,7 @@
 
     /**
      * Gets an item from the cache.
-     * 
+     *
      * @param key
      * @return a cache element, or null if there is no data in cache for this key
      * @throws IOException
@@ -57,7 +60,7 @@
 
     /**
      * Gets multiple items from the cache based on the given set of keys.
-     * 
+     *
      * @param keys
      * @return a map of K key to ICacheElement&lt;K, V&gt; element, or an empty map if there is no data in cache for any of these keys
      * @throws IOException
@@ -67,11 +70,11 @@
 
     /**
      * Gets items from the cache matching the given pattern.  Items from memory will replace those from remote sources.
-     * 
+     *
      * This only works with string keys.  It's too expensive to do a toString on every key.
-     * 
+     *
      * Auxiliaries will do their best to handle simple expressions.  For instance, the JDBC disk cache will convert * to % and . to _
-     * 
+     *
      * @param pattern
      * @return a map of K key to ICacheElement&lt;K, V&gt; element, or an empty map if there is no data matching the pattern.
      * @throws IOException
@@ -81,7 +84,7 @@
 
     /**
      * Removes an item from the cache.
-     * 
+     *
      * @param key
      * @return false if there was an error in removal
      * @throws IOException
@@ -91,7 +94,7 @@
 
     /**
      * Removes all cached items from the cache.
-     * 
+     *
      * @throws IOException
      */
     void removeAll()
@@ -106,35 +109,35 @@
 
     /**
      * Returns the current cache size in number of elements.
-     * 
+     *
      * @return number of elements
      */
     int getSize();
 
     /**
      * Returns the cache status.
-     * 
+     *
      * @return Alive or Error
      */
     CacheStatus getStatus();
 
     /**
      * Returns the cache stats.
-     * 
+     *
      * @return String of important historical information.
      */
     String getStats();
 
     /**
      * Returns the cache name.
-     * 
+     *
      * @return usually the region name.
      */
     String getCacheName();
 
     /**
      * Sets the key matcher used by get matching.
-     * 
+     *
      * @param keyMatcher
      */
     void setKeyMatcher( IKeyMatcher<K> keyMatcher );
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCache.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCache.java
index f3a5c40..7601996 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCache.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCache.java
@@ -36,7 +36,6 @@
 import org.apache.commons.jcs.access.exception.CacheException;
 import org.apache.commons.jcs.access.exception.ObjectNotFoundException;
 import org.apache.commons.jcs.auxiliary.AuxiliaryCache;
-import org.apache.commons.jcs.engine.CacheConstants;
 import org.apache.commons.jcs.engine.CacheStatus;
 import org.apache.commons.jcs.engine.behavior.ICache;
 import org.apache.commons.jcs.engine.behavior.ICacheElement;
@@ -242,9 +241,9 @@
     {
 
         if (cacheElement.getKey() instanceof String
-            && cacheElement.getKey().toString().endsWith(CacheConstants.NAME_COMPONENT_DELIMITER))
+            && cacheElement.getKey().toString().endsWith(NAME_COMPONENT_DELIMITER))
         {
-            throw new IllegalArgumentException("key must not end with " + CacheConstants.NAME_COMPONENT_DELIMITER
+            throw new IllegalArgumentException("key must not end with " + NAME_COMPONENT_DELIMITER
                 + " for a put operation");
         }
         else if (cacheElement.getKey() instanceof GroupId)
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheManager.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheManager.java
index 1d29b56..d735a47 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheManager.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheManager.java
@@ -43,7 +43,6 @@
 import org.apache.commons.jcs.auxiliary.AuxiliaryCacheAttributes;
 import org.apache.commons.jcs.auxiliary.AuxiliaryCacheFactory;
 import org.apache.commons.jcs.auxiliary.remote.behavior.IRemoteCacheConstants;
-import org.apache.commons.jcs.engine.CacheConstants;
 import org.apache.commons.jcs.engine.CompositeCacheAttributes;
 import org.apache.commons.jcs.engine.ElementAttributes;
 import org.apache.commons.jcs.engine.behavior.ICache;
@@ -62,6 +61,7 @@
 import org.apache.commons.jcs.utils.config.OptionConverter;
 import org.apache.commons.jcs.utils.threadpool.DaemonThreadFactory;
 import org.apache.commons.jcs.utils.threadpool.ThreadPoolManager;
+import org.apache.commons.jcs.utils.timing.ElapsedTimer;
 
 /**
  * Manages a composite cache. This provides access to caches and is the primary way to shutdown the
@@ -80,12 +80,20 @@
     /** JMX object name */
     public static final String JMX_OBJECT_NAME = "org.apache.commons.jcs:type=JCSAdminBean";
 
+    /** This is the name of the config file that we will look for by default. */
+    private static final String DEFAULT_CONFIG = "/cache.ccf";
+
     /** default region prefix */
     private static final String DEFAULT_REGION = "jcs.default";
 
+    /** Should we use system property substitutions. */
+    private static final boolean DEFAULT_USE_SYSTEM_PROPERTIES = true;
+
+    /** Once configured, you can force a reconfiguration of sorts. */
+    private static final boolean DEFAULT_FORCE_RECONFIGURATION = false;
+
     /** Caches managed by this cache manager */
-    private final ConcurrentMap<String, ICache<?, ?>> caches =
-        new ConcurrentHashMap<>();
+    private final ConcurrentMap<String, ICache<?, ?>> caches = new ConcurrentHashMap<>();
 
     /** Number of clients accessing this cache manager */
     private final AtomicInteger clients = new AtomicInteger(0);
@@ -117,12 +125,6 @@
     /** The Singleton Instance */
     private static CompositeCacheManager instance;
 
-    /** Should we use system property substitutions. */
-    private static final boolean DEFAULT_USE_SYSTEM_PROPERTIES = true;
-
-    /** Once configured, you can force a reconfiguration of sorts. */
-    private static final boolean DEFAULT_FORCE_RECONFIGURATION = false;
-
     /** Stack for those waiting for notification of a shutdown. */
     private final LinkedBlockingDeque<IShutdownObserver> shutdownObservers = new LinkedBlockingDeque<>();
 
@@ -156,7 +158,7 @@
      */
     public static synchronized CompositeCacheManager getInstance() throws CacheException
     {
-        return getInstance( CacheConstants.DEFAULT_CONFIG );
+        return getInstance( DEFAULT_CONFIG );
     }
 
     /**
@@ -304,7 +306,7 @@
      */
     public void configure() throws CacheException
     {
-        configure( CacheConstants.DEFAULT_CONFIG );
+        configure( DEFAULT_CONFIG );
     }
 
     /**
@@ -426,7 +428,7 @@
         // configure the cache
         CompositeCacheConfigurator configurator = newConfigurator();
 
-        long start = System.currentTimeMillis();
+        ElapsedTimer timer = new ElapsedTimer();
 
         // set default value list
         this.defaultAuxValues = OptionConverter.findAndSubst( CompositeCacheManager.DEFAULT_REGION,
@@ -453,8 +455,7 @@
         // setup preconfigured caches
         configurator.parseRegions( properties, this );
 
-        long end = System.currentTimeMillis();
-        log.info( "Finished configuration in {0} ms.", end - start);
+        log.info( "Finished configuration in {0} ms.", () -> timer.getElapsedTime());
 
         isConfigured = true;
     }
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 0c63fd0..e0b1bdb 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
@@ -30,7 +30,7 @@
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.stream.Collectors;
 
-import org.apache.commons.jcs.engine.CacheConstants;
+import org.apache.commons.jcs.engine.behavior.ICache;
 import org.apache.commons.jcs.engine.behavior.ICacheElement;
 import org.apache.commons.jcs.engine.behavior.ICompositeCacheAttributes;
 import org.apache.commons.jcs.engine.control.CompositeCache;
@@ -415,7 +415,7 @@
         boolean removed = false;
 
         // handle partial removal
-        if (key instanceof String && ((String) key).endsWith(CacheConstants.NAME_COMPONENT_DELIMITER))
+        if (key instanceof String && ((String) key).endsWith(ICache.NAME_COMPONENT_DELIMITER))
         {
             removed = removeByHierarchy(key);
         }