📄 objectpool.java
字号:
} /** * Sets the last used time for an object in the pool that is currently * in use. If the timestamp parameter is not set, this call does nothing. * Otherwise, the object is marked as last used at the current time. * @throws java.lang.IllegalArgumentException * Occurs when the object is not recognized by the factory or not * in the pool. * @throws java.lang.IllegalStateException * Occurs when the object is not currently in use. * @see #setTimestampUsed */ public void setLastUsed(Object object) { if (!trackLastUsed) return; Object ob = null; try { ob = factory.translateObject(object); } catch (Exception e) { throw new IllegalArgumentException("Pool " + getName() + " does not recognize object for last used time: " + object); } ObjectRecord rec = ob == null ? null : (ObjectRecord) objects.get(ob); if (rec == null) throw new IllegalArgumentException("Pool " + getName() + " does not recognize object for last used time: " + object); if (rec.isInUse()) rec.setLastUsed(); else throw new IllegalStateException("Cannot set last updated time for an object that's not in use!"); } /** * Indicates that an object is no longer valid, and should be removed from * the pool entirely. This should be called before the object is returned * to the pool (specifically, before factory.returnObject returns), or else * the object may be given out again by the time this is called! Also, you * still need to actually return the object to the pool by calling * releaseObject, if you aren't calling this during that process already. * @param object The object to invalidate, which must be the exact object * returned by getObject */ public void markObjectAsInvalid(Object object) { if (deadObjects == null) throw new IllegalStateException("Tried to use pool before it was Initialized or after it was ShutDown!"); deadObjects.add(object); //a synchronized set } /** * Returns an object to the pool. This must be the exact object that was * given out by getObject, and it must be returned to the same pool that * generated it. If other clients are blocked waiting on an object, the * object may be re-released immediately. * @throws java.lang.IllegalArgumentException * Occurs when the object is not in this pool. */ public void releaseObject(Object object) { log.debug("Pool " + this + " object released: " + object); Object pooled = null; try { factory.returnObject(object);//do this first pooled = factory.translateObject(object); } catch (Exception e) { return; // We can't release it if the factory can't recognize it } if (pooled == null) // We can't release it if the factory can't recognize it return; boolean removed = false; synchronized (objects) { ObjectRecord rec = (ObjectRecord) objects.get(pooled); if (rec == null) // Factory understands it, but we don't throw new IllegalArgumentException("Object " + object + " is not in pool " + poolName + "!"); if (!rec.isInUse()) return; // Must have been released by GC? if (object instanceof PooledObject) ((PooledObject) object).removePoolEventListener(this); removed = deadObjects.remove(object); rec.setInUse(false); if (removed) { log.debug("Object was dead: " + object); objects.remove(pooled); rec.close(); } // end of if () }//end of synch on objects if (removed) { try { factory.deleteObject(pooled); } catch (Exception e) { log.error("Pool " + this + " factory (" + factory.getClass().getName() + " delete error: ", e); } fillToMin(); /*FIXME --MINSIZE if(objects.size() < minSize) createNewObject(null); */ } if (removed) log.debug("Pool " + this + " destroyed object " + object + "."); else log.debug("Pool " + this + " returned object " + object + " to the pool."); permits.release(); /* if(blocking) { synchronized(this) { notify(); } } */ } private int getUsedCount() { int total = 0; synchronized (objects) { for (Iterator it = new HashSet(objects.values()).iterator(); it.hasNext();) { ObjectRecord or = (ObjectRecord) it.next(); if (or != null && or.isInUse()) ++total; } } return total; } /** * Returns the pool name and status. */ public String toString() { return poolName + " [" + getUsedCount() + "/" + (objects == null ? 0 : objects.size()) + "/" + (maxSize == 0 ? "Unlimited" : Integer.toString(maxSize)) + "]"; } // ---- PoolEventListener Implementation ---- /** * If the object has been closed, release it. */ public void objectClosed(PoolEvent evt) { releaseObject(evt.getSource()); } /** * If the invalidateOnError flag is set, the object will be removed from * the pool entirely when the client has finished with it. */ public void objectError(PoolEvent evt) { if (invalidateOnError || evt.isCatastrophic()) markObjectAsInvalid(evt.getSource()); } /** * If we're tracking the last used times, update the last used time for the * specified object. */ public void objectUsed(PoolEvent evt) { if (!trackLastUsed) return; setLastUsed(evt.getSource()); } long getNextGCMillis(long now) { long t = lastGC + gcIntervalMillis - now; log.debug("getNextGCMillis(): returning " + t); if (!runGC) return Long.MAX_VALUE; return t; } // Allow GC if we're within 10% of the desired interval boolean isTimeToGC() { long now; now = System.currentTimeMillis(); log.debug("isTimeToGC(): " + (now >= lastGC + Math.round((float) gcIntervalMillis * 0.9f))); return now >= lastGC + Math.round((float) gcIntervalMillis * 0.9f); } void runGCandShrink() { log.debug("runGCandShrink(): runGC = " + runGC + "; idleTimeout = " + idleTimeout); if (runGC || idleTimeout) { HashSet objsCopy; synchronized (objects) { objsCopy = new HashSet(objects.values()); } if (runGC) { // Garbage collection - return any object that's been out too long with no use Iterator it = objsCopy.iterator(); while (it.hasNext()) { ObjectRecord rec = (ObjectRecord) it.next(); if (rec != null && rec.isInUse() && rec.getMillisSinceLastUse() >= gcMinIdleMillis) { releaseObject(rec.getClientObject()); } } } if (idleTimeout) { // Shrinking the pool - remove objects from the pool if they have not been used in a long time // Find object eligible for removal HashSet eligible = new HashSet(); Iterator it = objsCopy.iterator(); while (it.hasNext()) { ObjectRecord rec = (ObjectRecord) it.next(); if (rec != null && !rec.isInUse() && rec.getMillisSinceLastUse() > idleTimeoutMillis) eligible.add(rec); } // Calculate max number of objects to remove without replacing int max = Math.round(eligible.size() * maxIdleShrinkPercent); if (max == 0 && eligible.size() > 0) max = 1; int count = 0; // Attempt to remove that many objects it = eligible.iterator(); while (it.hasNext()) { try { // Delete the object ObjectRecord rec = (ObjectRecord) it.next(); if (rec != null) { rec.setInUse(true); // Don't let someone use it while we destroy it Object pooled = rec.getObject(); synchronized (objects) { objects.remove(pooled); } //removeObject(pooled); try { factory.deleteObject(pooled); } catch (Exception e) { log.error("Pool " + this + " factory (" + factory.getClass().getName() + " delete error: ", e); } rec.close(); ++count; } fillToMin(); /*FIXME --MINSIZE if(count > max || objects.size() < minSize) createNewObject(null); */ } catch (ConcurrentModificationException e) { } } } } lastGC = System.currentTimeMillis(); } /** * Removes an object from the pool. Only one thread can add or remove * an object at a time. */ /* private void removeObject(Object pooled) { synchronized(objects) { objects.remove(pooled); } } */ /** * Creates a new Object. * @param parameters If <b>true</b>, then the object is locked and * translated by the factory, and the resulting object * returned. If <b>false</b>, then the object is left in the * pool unlocked. */ private ObjectRecord createNewObject(Object parameters) { Object ob = null; try { ob = factory.createObject(parameters); } catch (Exception ex) { throw new RuntimeException("Could not create connection"); } if (ob != null) { // if factory can create object ObjectRecord rec = new ObjectRecord(ob); synchronized (objects) { objects.put(ob, rec); } return rec; } else { throw new RuntimeException("could not create new object!"); } } public void fillToMin() { Collection newMCs = new ArrayList(); try { while (objects.size() < minSize) { newMCs.add(getObject(null)); } // end of while () } catch (Exception re) { //Whatever the reason, stop trying to add more! } // end of try-catch for (Iterator i = newMCs.iterator(); i.hasNext();) { releaseObject(i.next()); } // end of for () }}class BeanFactory extends PoolObjectFactory { private Class beanClass; private Logger log = Logger.getLogger(BeanFactory.class); public BeanFactory(Class beanClass) { try { beanClass.getConstructor(new Class[0]); } catch (NoSuchMethodException e) { throw new IllegalArgumentException("Bean class doesn't have no-arg constructor!"); } this.beanClass = beanClass; } public void poolStarted(ObjectPool pool) { super.poolStarted(pool); } public Object createObject(Object parameters) { try { return beanClass.newInstance(); } catch (Exception e) { log.error("Unable to create instance of " + beanClass.getName(), e); } return null; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -