1
\$\begingroup\$

I have a project, that creates a custom DataBaseConnection pool as below:

 public abstract class ObjectPool<T> {


    private final long expirationTime;

    private final Integer minimumConnection;

    private final Integer maximumConnection;

    private final Integer overFlowWaitTime;

    /**
     * Hash tables to hold the used and unused objects.
     */
    private final Hashtable<T, Long> using, free;


    public ObjectPool() {
        this.expirationTime = 20000;
        this.minimumConnection = 5;
        this.maximumConnection = 20;
        this.overFlowWaitTime = 2000;
        this.using = new Hashtable<T, Long>();
        this.free = new Hashtable<T, Long>();
    }


    protected abstract T create();


    public abstract boolean validate(T obj);


    public abstract void expire(T obj);


    public final synchronized T checkOut() {
        T objPool;
        if ((this.using.size() + this.free.size()) >= maximumConnection) {
           //Maximum connections reached waiting to get the unlocked connections
            while (this.free.size() <= 0) {
                try {
                    Thread.sleep(overFlowWaitTime);
                } catch (InterruptedException e) {
                    System.out.println(e.getMessage());
                }
            }
        }
        if (this.free.size() > 0) {
            Enumeration<T> enumObj = this.free.keys();
            long now = System.currentTimeMillis();
            while (enumObj.hasMoreElements()) {
                objPool = enumObj.nextElement();
                // Checking object expired or not, and if expired removed from
                // the unlocked table.
                if ((now - this.free.get(objPool)) > this.expirationTime) {
                    this.free.remove(objPool);
                    this.expire(objPool);
                    objPool = null;
                    if (this.free.size() < this.minimumConnection) {
                        T newObj = this.create();
                        this.free.put(newObj, System.currentTimeMillis());
                    }
                } else {
                    if (this.validate(objPool)) {
                        this.free.remove(objPool);
                        this.using.put(objPool, now);
                        return (objPool);
                    } else {
                        this.free.remove(objPool);
                        this.expire(objPool);
                        objPool = null;
                    }
                }
            }
        }
        T newObj = this.create();
        this.using.put(newObj, System.currentTimeMillis());
        return newObj;
    }


    public final void checkIn(final T obj) {

        this.using.remove(obj);
        this.free.put(obj, System.currentTimeMillis());
    }

 }

And the DB connection pool as:

public final class DBConnectionPool extends ObjectPool<Connection> {

    /**
     * MySQL datasource to be used.
     */
    private static MysqlDataSource datasource;
    /**
     * DBConnection class object for object pooling.
     */
    private static DBConnection connection = null;

    /**
     * Private constructor for singleton implementation.
     */
    private DBConnection() {
        datasource = new MysqlDataSource();
        datasource.setDatabaseName("dbname");
        datasource.setUser("username");
        datasource.setPassword("password");
        datasource.setServerName("host");
        datasource.setPort(3060);

    }

    /**
     * get the datasource of this connection pool.
     * 
     * @return {@link DataSource} object.
     */
    public DataSource getDataSource() {
        return datasource;
    }

    /**
     * Create new datasource if there is one not already available.
     * 
     * @return MySQLDataSource object.
     */
    public static synchronized DBConnection getConnection() {
        if (connection == null) {
            connection = new DBConnection();
        }
        return connection;
    }

    @Override
    protected Connection create() {
        Connection dbConnection = null;
        if (datasource != null) {
            try {
                dbConnection = datasource.getConnection();
            } catch (SQLException e) {
                System.out.println("Unable to create connection", e);
            }
        }
        return dbConnection;
    }

    @Override
    public boolean validate(final Connection objPool) {
        try {
            if (objPool.isClosed()) {
                return false;
            }
        } catch (SQLException e) {
            System.out.println("Unable to validate the connection", e);
            return false;
        }
        return true;
    }

    @Override
    public void expire(final Connection objPool) {

        try {
            objPool.close();
        } catch (SQLException e) {
            System.out.println("Unable to close the connection ", e);
        }
    }

}

After running for some time the application slows down. We suspect our connection pooling has some multi-threading issue. We have noticed unsynchronized public final void checkIn(final T obj). Could this be a problem.

Can anyone suggest any improvement?

\$\endgroup\$
  • 2
    \$\begingroup\$ What is the compelling reason for not using one of the several publicly available libraries that do this? Writing a good object pool is not trivial. It will be much less expensive to bring one in than to write, correct, and maintain this code. \$\endgroup\$ – Eric Stein Nov 24 '15 at 15:26
  • \$\begingroup\$ We could suggest plenty of improvements. Do you care about anything other than your performance issue? Yes, not locking on check-in might be a problem. Using synchronized methods instead of an internal lock object might also be the problem. Or maybe the problem isn't in any of this code. You're going to need to use a performance tuning tool to find out where your bottleneck is. Otherwise, we're all just guessing. \$\endgroup\$ – Eric Stein Nov 24 '15 at 15:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.