📄 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 + -