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: user-unsubscr...@commons.apache.org For additional commands, e-mail: user-h...@commons.apache.org