Hello -
I recently observed in my prod system a case of GenericObjectPool not
respecting its limits. I had a pool of maxActive 10 that ultimately served out
objects to every single thread in my app server, ultimately bringing it down
when the pooled resource stopped responding. I have reproduced a small test
case that shows a pool with max size one that serves out more than one object
when hit by 5 concurrent threads. Hopefully I'm just doing something obviously
wrong. Any thoughts?
Ken
import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.commons.pool.PoolableObjectFactory;
import java.util.List;
import java.util.ArrayList;
import java.util.Random;
public class MaxActiveExceeded {
public static void main(String[] args) {
Pool pool = new Pool(); //just to instantiate
List<DoSomething> tlist = new ArrayList<DoSomething>();
for(int i = 0; i < 5; i++) {
DoSomething x = new DoSomething("" + i);
tlist.add(x);
}
for(DoSomething x : tlist) {
x.start();
try {
Thread.sleep(100);
} catch(InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use
File | Settings | File Templates.
}
}
}
public static Object testBorrow() {
Object ctx = null;
try {
System.out.println("---Idle " + ImageNowConnectionPool.getNumIdle()
+ " Active " + ImageNowConnectionPool.getNumActive() + " : " +
System.currentTimeMillis());
ctx = Pool.getConnection();
Pool.releaseConnection(ctx);
} catch (Exception e) {
System.out.println("msg " + ctx + " -- " + e.getLocalizedMessage()
+ " : " + System.currentTimeMillis());
}
return ctx;
}
private static class DoSomething extends Thread {
private DoSomething(String name) {
super(name);
}
public void run() {
System.out.println("Thread running " + getName());
Object o = testBorrow();
System.out.println("Thread stopping " + getName() + ", object
returned - " + o);
}
}
private static class Pool {
private static final int MAXACTIVE = 1;
private static final long MAXWAIT = 500;
private static final int MAXIDLE = -1;
private static final int MINIDLE = 0;
private static final boolean TESTONBORROW = false;
private static final boolean TESTWHILEIDLE = false;
private static final boolean TESTONRETURN = false;
private static final long TIMEBETWEENEVICTRUNS = -1;
private static final int NUMTESTSPEREVICTRUN = 2;
private static final long MINEVICTABLEIDLETIME = -1;
private static final GenericObjectPool<Object> POOL = new
GenericObjectPool<Object>(new ObjectFactory(),
MAXACTIVE, GenericObjectPool.WHEN_EXHAUSTED_BLOCK, MAXWAIT,
MAXIDLE, MINIDLE,
TESTONBORROW, TESTONRETURN, TIMEBETWEENEVICTRUNS,
NUMTESTSPEREVICTRUN, MINEVICTABLEIDLETIME,
TESTWHILEIDLE);
public static Object getConnection(){
Object o = null;
try {
System.out.println("pre-borrow " + Thread.currentThread() + ":
Idle" + POOL.getNumIdle() + " Active " + POOL.getNumActive() + " : " +
System.currentTimeMillis());
o = POOL.borrowObject();
System.out.println("post-borrow " + Thread.currentThread() + ":
Idle" + POOL.getNumIdle() + " Active " + POOL.getNumActive() + " : " +
System.currentTimeMillis());
} catch (Exception e) {
System.out.println("****Error trying to borow - " +
Thread.currentThread() + ":" + e.getMessage() );
// System.out.println("borrow exception " +
Thread.currentThread() + ": Idle" + POOL.getNumIdle() + " Active " +
POOL.getNumActive() + " : " + System.currentTimeMillis());
// e.printStackTrace();
}
return o;
}
public static void releaseConnection(Object o){
try {
System.out.println("pre-release " + Thread.currentThread() + ":
Idle" + POOL.getNumIdle() + " Active " + POOL.getNumActive() + " : " +
System.currentTimeMillis());
POOL.returnObject(o);
System.out.println("post-release " + Thread.currentThread() +
": Idle" + POOL.getNumIdle() + " Active " + POOL.getNumActive() + " : " +
System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static class ObjectFactory implements PoolableObjectFactory<Object>
{
// returns a new connection to imagenow
public Object makeObject() {
Object retObj = null;
try {
retObj = login();
System.out.println("make obj" + retObj + " : " +
System.currentTimeMillis() + Thread.currentThread());
} catch (Exception e) {
e.printStackTrace();
}
return retObj;
}
public void destroyObject(Object obj) {
System.out.println("destroy obj" + obj + " : " +
System.currentTimeMillis() + Thread.currentThread());
}
public boolean validateObject(Object obj) {
boolean isValid = false;
if(obj == null) {
System.out.println("validation obj is null " +
Thread.currentThread());
} else {
try {
System.out.println("about to validate " +
Thread.currentThread());
Random r = new Random();
Thread.sleep(5000 + r.nextInt(20000));
isValid = true;
System.out.println("validate obj " + obj + " valid = " +
isValid + " : " + System.currentTimeMillis() + Thread.currentThread());
} catch (Exception e) {
e.printStackTrace();
}
}
return isValid;
}
public void activateObject(Object obj) {
System.out.println("activate" + obj + " : " +
System.currentTimeMillis() + Thread.currentThread());
}
public void passivateObject(Object obj) {
System.out.println("passivate" + obj + " : " +
System.currentTimeMillis() + Thread.currentThread());
}
/*-----------------------------------*/
private static Object login() throws Exception {
System.out.println("about to login " + Thread.currentThread());
Random r = new Random();
Thread.sleep(5000 + r.nextInt(20000));
System.out.println("login complete " + Thread.currentThread());
return new Object();
}
}
}
----------------------------------------------------------------------
CONFIDENTIALITY NOTICE: This email and any files transmitted with it are
confidential and intended solely for the use of the individual or entity to
which they are addressed. If you are not the intended recipient, you may not
review, copy or distribute this message. If you have received this email in
error, please notify the sender immediately and delete the original message.
Neither the sender nor the company for which he or she works accepts any
liability for any damage caused by any virus transmitted by this email.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]