You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by rd...@apache.org on 2006/02/14 21:46:01 UTC

svn commit: r377826 - in /jakarta/commons/proper/pool/trunk/src/java/org/apache/commons/pool/impl: GenericKeyedObjectPool.java GenericObjectPool.java

Author: rdonkin
Date: Tue Feb 14 12:45:59 2006
New Revision: 377826

URL: http://svn.apache.org/viewcvs?rev=377826&view=rev
Log:
Switches from Thread to java.util.TimerTask for evictions. This is a far more efficient implementation for highly loaded systems. Original patch contributed by Matt Bishop. Patch committed contributed by Sandy McArthur. Issue #36581.

Modified:
    jakarta/commons/proper/pool/trunk/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java
    jakarta/commons/proper/pool/trunk/src/java/org/apache/commons/pool/impl/GenericObjectPool.java

Modified: jakarta/commons/proper/pool/trunk/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/trunk/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java?rev=377826&r1=377825&r2=377826&view=diff
==============================================================================
--- jakarta/commons/proper/pool/trunk/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java (original)
+++ jakarta/commons/proper/pool/trunk/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java Tue Feb 14 12:45:59 2006
@@ -25,6 +25,7 @@
 import java.util.TreeMap;
 import java.util.LinkedList;
 import java.util.HashSet;
+import java.util.TimerTask;
 
 import org.apache.commons.pool.BaseKeyedObjectPool;
 import org.apache.commons.pool.KeyedObjectPool;
@@ -576,7 +577,7 @@
     public synchronized void setMinIdle(int poolSize) {
         _minIdle = poolSize;
     }
-    
+
     /**
      * Returns the minimum number of idle objects in pool to maintain (per key)
      * @return the minimum number of idle objects in pool to maintain (per key)
@@ -585,7 +586,7 @@
     public synchronized int getMinIdle() {
         return _minIdle;
     }
-    
+
     /**
      * When <tt>true</tt>, objects will be
      * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
@@ -867,7 +868,7 @@
     }
 
     /**
-     * Method clears oldest 15% of objects in pool.  The method sorts the 
+     * Method clears oldest 15% of objects in pool.  The method sorts the
      * objects into a TreeMap and then iterates the first 15% for removal
      */
     public synchronized void clearOldest() {
@@ -884,11 +885,11 @@
                 map.put(pair, key);
             }
         }
-        
+
         // Now iterate created map and kill the first 15% plus one to account for zero
         Set setPairKeys = map.entrySet();
         int itemsToRemove = ((int) (map.size() * 0.15)) + 1;
-        
+
         Iterator iter = setPairKeys.iterator();
         while (iter.hasNext() && itemsToRemove > 0) {
             Map.Entry entry = (Map.Entry) iter.next();
@@ -914,7 +915,7 @@
         }
         notifyAll();
     }
-     
+
     public synchronized void clear(Object key) {
         LinkedList pool = (LinkedList)(_poolMap.remove(key));
         if(null == pool) {
@@ -1017,12 +1018,12 @@
     }
 
     /**
-     * Registers a key for pool control. 
-     * 
+     * Registers a key for pool control.
+     *
      * If <i>populateImmediately</i> is <code>true</code>, the pool will immediately commence
      * a sustain cycle. If <i>populateImmediately</i> is <code>false</code>, the pool will be
      * populated when the next schedules sustain task is run.
-     * 
+     *
      * @param key - The key to register for pool control.
      * @param populateImmediately - If this is <code>true</code>, the pool
      * will start a sustain cycle immediately.
@@ -1033,7 +1034,7 @@
             pool = new LinkedList();
             _poolMap.put(key,pool);
         }
-        
+
         if (populateImmediately) {
             try {
                 // Create the pooled objects
@@ -1044,7 +1045,7 @@
             }
         }
     }
-    
+
     public synchronized void close() throws Exception {
         clear();
         _poolMap = null;
@@ -1136,9 +1137,9 @@
                             _factory.destroyObject(key,pair.value);
 
                             // Do not remove the key from the _poolList or _poolmap, even if the list
-                            // stored in the _poolMap for this key is empty when the 
+                            // stored in the _poolMap for this key is empty when the
                             // {@link #getMinIdle <i>minIdle</i>} is > 0.
-                            // 
+                            //
                             // Otherwise if it was the last object for that key, drop that pool
                             if ((_minIdle == 0) && (((LinkedList)(_poolMap.get(key))).isEmpty())) {
                                 _poolMap.remove(key);
@@ -1166,7 +1167,7 @@
      */
     private synchronized void ensureMinIdle() throws Exception {
         Iterator iterator = _poolMap.keySet().iterator();
-   
+
         //Check if should sustain the pool
         if (_minIdle > 0) {
             // Loop through all elements in _poolList
@@ -1184,7 +1185,7 @@
     /**
      * Re-creates any needed objects to maintain the minimum levels of
      * pooled objects for the specified key.
-     * 
+     *
      * This method uses {@link #calculateDefecit} to calculate the number
      * of objects to be created. {@link #calculateDefecit} can be overridden to
      * provide a different method of calculating the number of objects to be
@@ -1195,13 +1196,13 @@
     private synchronized void ensureMinIdle(Object key) throws Exception {
         // Calculate current pool objects
         int numberToCreate = calculateDefecit(key);
-        
+
         //Create required pool objects, if none to create, this loop will not be run.
         for (int i = 0; i < numberToCreate; i++) {
             addObject(key);
         }
     }
-    
+
     //--- non-public methods ----------------------------------------
 
     /**
@@ -1215,10 +1216,8 @@
             _evictor = null;
         }
         if(delay > 0) {
-            _evictor = new Evictor(delay);
-            Thread t = new Thread(_evictor);
-            t.setDaemon(true);
-            t.start();
+            _evictor = new Evictor();
+            GenericObjectPool.EVICTION_TIMER.schedule(_evictor, delay, delay);
         }
     }
 
@@ -1271,23 +1270,23 @@
         }
         return active;
     }
-    
+
     /**
      * This returns the number of objects to create during the pool
-     * sustain cycle. This will ensure that the minimum number of idle 
+     * sustain cycle. This will ensure that the minimum number of idle
      * connections is maintained without going past the maxPool value.
      * <p>
-     * This method has been left public so derived classes can override 
-     * the way the defecit is calculated. ie... Increase/decrease the pool 
+     * This method has been left public so derived classes can override
+     * the way the defecit is calculated. ie... Increase/decrease the pool
      * size at certain times of day to accomodate for usage patterns.
-     *  
+     *
      * @param key - The key of the pool to calculate the number of
      *              objects to be re-created
      * @return The number of objects to be created
      */
     private int calculateDefecit(Object key) {
         int objectDefecit = 0;
-        
+
         //Calculate no of objects needed to be created, in order to have
         //the number of pooled objects < maxActive();
         objectDefecit = getMinIdle() - getNumIdle(key);
@@ -1295,8 +1294,8 @@
             int growLimit = Math.max(0, getMaxActive() - getNumActive(key) - getNumIdle(key));
             objectDefecit = Math.min(objectDefecit, growLimit);
         }
-        
-        // Take the maxTotal limit into account 
+
+        // Take the maxTotal limit into account
         if (getMaxTotal() > 0) {
             int growLimit = Math.max(0, getMaxTotal() - getNumActive() - getNumIdle());
             objectDefecit = Math.min(objectDefecit, growLimit);
@@ -1309,7 +1308,7 @@
 
     /**
      * A simple "struct" encapsulating an object instance and a timestamp.
-     * 
+     *
      * Implements Comparable, objects are sorted from old to new.
      */
     class ObjectTimestampPair implements Comparable {
@@ -1340,44 +1339,22 @@
     }
 
     /**
-     * The idle object evictor thread.
+     * The idle object evictor {@link TimerTask}.
      * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis
      */
-    class Evictor implements Runnable {
-        private boolean _cancelled = false;
-        private long _delay = 0L;
-
-        public Evictor(long delay) {
-            _delay = delay;
-        }
-
-        void cancel() {
-            _cancelled = true;
-        }
-
+    private class Evictor extends TimerTask {
         public void run() {
-            while(!_cancelled) {
-                long sleeptime = 0L;
-                synchronized(GenericKeyedObjectPool.this) {
-                    sleeptime = _timeBetweenEvictionRunsMillis;
-                }
-                try {
-                    Thread.sleep(sleeptime);
-                } catch(Exception e) {
-                    ; // ignored
-                }
-                //Evict from the pool
-                try {
-                    evict();
-                } catch(Exception e) {
-                    ; // ignored
-                }
-                //Re-create the connections.
-                try {
-                    ensureMinIdle();
-                } catch (Exception e) { 
-                    ; // ignored
-                }
+            //Evict from the pool
+            try {
+                evict();
+            } catch(Exception e) {
+                // ignored
+            }
+            //Re-create the connections.
+            try {
+                ensureMinIdle();
+            } catch (Exception e) {
+                // ignored
             }
         }
     }
@@ -1558,7 +1535,7 @@
     private KeyedPoolableObjectFactory _factory = null;
 
     /**
-     * My idle object eviction thread, if any.
+     * My idle object eviction {@link TimerTask}, if any.
      */
     private Evictor _evictor = null;
 

Modified: jakarta/commons/proper/pool/trunk/src/java/org/apache/commons/pool/impl/GenericObjectPool.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/trunk/src/java/org/apache/commons/pool/impl/GenericObjectPool.java?rev=377826&r1=377825&r2=377826&view=diff
==============================================================================
--- jakarta/commons/proper/pool/trunk/src/java/org/apache/commons/pool/impl/GenericObjectPool.java (original)
+++ jakarta/commons/proper/pool/trunk/src/java/org/apache/commons/pool/impl/GenericObjectPool.java Tue Feb 14 12:45:59 2006
@@ -20,6 +20,8 @@
 import java.util.NoSuchElementException;
 import java.util.LinkedList;
 import java.util.ListIterator;
+import java.util.Timer;
+import java.util.TimerTask;
 
 import org.apache.commons.pool.BaseObjectPool;
 import org.apache.commons.pool.ObjectPool;
@@ -257,6 +259,13 @@
      */
     public static final long DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS = -1;
 
+    //--- package constants -------------------------------------------
+
+    /**
+     * Idle object evition Timer. Shared between all {@link GenericObjectPool}s and {@link GenericKeyedObjectPool} s.
+     */
+    static final Timer EVICTION_TIMER = new Timer(true);
+
     //--- constructors -----------------------------------------------
 
     /**
@@ -1063,10 +1072,8 @@
             _evictor = null;
         }
         if(delay > 0) {
-            _evictor = new Evictor(delay);
-            Thread t = new Thread(_evictor);
-            t.setDaemon(true);
-            t.start();
+            _evictor = new Evictor();
+            EVICTION_TIMER.schedule(_evictor, delay, delay);
         }
     }
 
@@ -1112,41 +1119,22 @@
     }
 
     /**
-     * The idle object evictor thread.
+     * The idle object evictor {@link TimerTask}.
      * @see GenericObjectPool#setTimeBetweenEvictionRunsMillis
      */
-    class Evictor implements Runnable {
-        private volatile boolean _cancelled = false;
-        private long _delay = 0L;
-
-        public Evictor(long delay) {
-            _delay = delay;
-        }
-
-        void cancel() {
-            _cancelled = true;
-        }
-
+    private class Evictor extends TimerTask {
         public void run() {
-            while(!_cancelled) {
-                try {
-                    Thread.sleep(_delay);
-                } catch(Exception e) {
-                    // ignored
-                }
-                try {
-                    evict();
-                } catch(Exception e) {
-                    // ignored
-                }
-                try {
-                    ensureMinIdle();
-                } catch(Exception e) {
-                    // ignored
-                }
+            try {
+                evict();
+            } catch(Exception e) {
+                // ignored
+            }
+            try {
+                ensureMinIdle();
+            } catch(Exception e) {
+                // ignored
             }
         }
-
     }
 
     /**
@@ -1328,7 +1316,7 @@
     private int _numActive = 0;
 
     /**
-     * My idle object eviction thread, if any.
+     * My idle object eviction {@link TimerTask}, if any.
      */
     private Evictor _evictor = null;
 



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org