2
\$\begingroup\$

I have read the code reviews on this website: this one and this one

So creating the pool in itself might not be that difficult, I'm more worried about the client closing the connection or the connection not being given back to the pool.

So I have tried to implement this answer.

public interface Connection {
 Object read();
 void close();
 void rollback();
}
public class ConnectionImpl implements Connection{
 public ConnectionImpl(String connectionString) {
 }
 @Override
 public Object read() {
 return null;
 }
 @Override
 public void close() {
 // do stuff to close the connection
 }
 @Override
 public void rollback() {
 // do stuff to go back to a valid state
 }
}
/**
 * This will wrap the connectionImpl and make sure the client doesn't close the connection himself, it will instead release it
 */
public class ConnectionWrapper implements Connection {
 private Connection m_connection;
 private ConnectionPool connectionPool;
 public ConnectionWrapper(Connection connection, ConnectionPool connectionPool) {
 m_connection = connection;
 }
 @Override
 public Object read() {
 return m_connection.read();
 }
 @Override
 public void close() {
 connectionPool.release(m_connection);
 }
 @Override
 public void rollback() {
 m_connection.rollback();
 }
 @Override
 protected void finalize() throws Throwable {
 try{
 close();
 }finally {
 super.finalize();
 }
 }
}
public class ConnectionPool {
 private BlockingQueue<Connection> m_connections;
 private List<Connection> m_usedConnections;
 private int m_maxConnectionNumber;
 private String m_connectionString;
 private AtomicInteger m_currentConnectionNumber;
 public ConnectionPool(int maxConnectionNumber, String connectionString) {
 m_connections = new ArrayBlockingQueue<>(maxConnectionNumber);
 m_usedConnections = new ArrayList<>();
 m_maxConnectionNumber = maxConnectionNumber;
 m_connectionString = connectionString;
 m_currentConnectionNumber = new AtomicInteger(0);
 }
 public Connection get() throws InterruptedException {
 createNewConnectionIfNecessary();
 Connection connection = m_connections.take();
 m_usedConnections.add(connection);
 return connection;
 }
 public void release(Connection connection) {
 int usedConnectionIndex = m_usedConnections.indexOf(connection);
 if (usedConnectionIndex == -1) {
 return;
 }
 connection.rollback();
 m_usedConnections.remove(usedConnectionIndex);
 m_connections.offer(connection);
 }
 private void createNewConnectionIfNecessary() {
 synchronized(m_connections) {
 if (m_connections.isEmpty() && m_currentConnectionNumber.get() < m_maxConnectionNumber) {
 Connection connection = new ConnectionImpl(m_connectionString);
 ConnectionWrapper connectionWrapper = new ConnectionWrapper(connection,this);
 m_connections.add(connectionWrapper);
 m_currentConnectionNumber.getAndIncrement();
 }
 }
 }
}

So, few questions:

  1. is my implementation thread-safe?
  2. Is there any other way my implementation could result in not releasing the connection?
  3. I know that the finalize method might not be called, resulting in a Connection leaking. Is there any way to prevent this?
  4. In general, any other advice?
asked Sep 9, 2016 at 7:40
\$\endgroup\$

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.