Код необходимости создания пула соединений в java

Нужен код для создания пула соединений в java? Как мы убеждаемся, что пул соединений не возвращает тот же объект, который уже используется? Как происходит, если клиент закрыл соединение после его извлечения из пула соединений?

Обновление 1:

Я хочу создать это в простых выражениях Java и хочу посмотреть, как он работает в режиме многопоточности. Я имею в виду, какие методы будут синхронизированы, а какие нет. Также будет ли этот класс публичным классом? Если да, то любой может получить доступ к этому классу и повторно инициализировать пул соединений?

Обновление 2:

У меня есть код, как показано ниже. Но я не понимаю, как "Закрытие соединения из пула возвращает его в пул, оно физически не закрывает соединение". Также я не понял этого: "Потому что, если соединение было заимствовано из пула и еще не возвращено, оно не" доступно "и не может быть перераспределено другому клиенту пула".

import java.util.*;
import java.sql.*;

class ConnectionPoolManager
{

 String databaseUrl = "jdbc:mysql://localhost:3306/myDatabase";
 String userName = "userName";
 String password = "userPass";

 Vector connectionPool = new Vector();

 public ConnectionPoolManager()
 {
  initialize();
 }

 public ConnectionPoolManager(
  //String databaseName,
  String databaseUrl,
  String userName,
  String password
  )
 {
  this.databaseUrl = databaseUrl;
  this.userName = userName;
  this.password = password;
  initialize();
 }

 private void initialize()
 {
  //Here we can initialize all the information that we need
  initializeConnectionPool();
 }

 private void initializeConnectionPool()
 {
  while(!checkIfConnectionPoolIsFull())
  {
   System.out.println("Connection Pool is NOT full. Proceeding with adding new connections");
   //Adding new connection instance until the pool is full
   connectionPool.addElement(createNewConnectionForPool());
  }
  System.out.println("Connection Pool is full.");
 }

 private synchronized boolean checkIfConnectionPoolIsFull()
 {
  final int MAX_POOL_SIZE = 5;

  //Check if the pool size
  if(connectionPool.size() < 5)
  {
   return false;
  }

  return true;
 }

 //Creating a connection
 private Connection createNewConnectionForPool()
 {
  Connection connection = null;

  try
  {
   Class.forName("com.mysql.jdbc.Driver");
   connection = DriverManager.getConnection(databaseUrl, userName, password);
   System.out.println("Connection: "+connection);
  }
  catch(SQLException sqle)
  {
   System.err.println("SQLException: "+sqle);
   return null;
  }
  catch(ClassNotFoundException cnfe)
  {
   System.err.println("ClassNotFoundException: "+cnfe);
   return null;
  }

  return connection;
 }

 public synchronized Connection getConnectionFromPool()
 {
  Connection connection = null;

  //Check if there is a connection available. There are times when all the connections in the pool may be used up
  if(connectionPool.size() > 0)
  {
   connection = (Connection) connectionPool.firstElement();
   connectionPool.removeElementAt(0);
  }
  //Giving away the connection from the connection pool
  return connection;
 }

 public synchronized void returnConnectionToPool(Connection connection)
 {
  //Adding the connection from the client back to the connection pool
  connectionPool.addElement(connection);
 }

 public static void main(String args[])
 {
  ConnectionPoolManager ConnectionPoolManager = new ConnectionPoolManager();
 }

}

Ответ 1

Нужен код для создания пула соединений в java?

Не уверен, в чем вопрос, но не создайте еще один пул соединений, используйте существующее решение, например C3P0, Apache DBCP, Proxool или BoneCP (новый игрок в этом поле). Я бы использовал C3P0.

Как мы убеждаемся, что пул соединений не возвращает тот же самый объект, который уже используется?

Потому что если соединение заимствовано из пула и еще не возвращено, оно просто не в пуле и не может быть назначено другому клиенту пула (ресурсы удаляются из пула, пока они не будут возвращены).

Как происходит, если клиент закрыл соединение после его извлечения из пула соединений?

Соединение, которое клиент получает из пула, на самом деле не является java.sql.Connection, это оболочка (прокси) для java.sql.Connection, который настраивает поведение некоторых методов. Метод close() является одним из них и не закрывает экземпляр Connection, но возвращает его в пул.

Ответ 2

Не пишите свои собственные. Там есть много библиотек, которые сделают это для вас, которые с открытым исходным кодом и удобны в использовании, и будут решать все проблемы, с которыми вы столкнетесь, пытаясь сделать это сами.

Вот простой пример, который использует Apache Commons DBCP и Commons Pool:

Сначала настройте DataSource.

javax.sql.DataSource source = new org.apache.commons.dbcp.BasicDataSource();
source.setDriverClassName("com.mysql.jdbc.Driver");
source.setUsername("username");
source.setPassword("password");
source.setUrl("jdbc:mysql://localhost:3306/myDatabase");

Как только у вас есть DataSource, легко получить соединение из пула.

java.sql.Connection connection = source.getConnection();

закрытие соединения вернет его в пул для вас.

connection.close();

Ответ 3

Я надеюсь, что этот исходный код поможет http://jagadeeshmanne.blogspot.in/2014/03/connection-pool-in-java-jdbc.html

Configuration.java

package com.jmanne.utils;

public class Configuration {

 public String DB_USER_NAME ;

 public String DB_PASSWORD ;

 public String DB_URL;

 public String DB_DRIVER;

 public Integer DB_MAX_CONNECTIONS;

 public Configuration(){
  init();
 }

 private static Configuration configuration = new Configuration();

 public static Configuration getInstance(){ 
  return configuration;
 }

 private void init(){
  DB_USER_NAME = "root"
  DB_PASSWORD = "root"
  DB_URL = "jdbc:mysql://localhost:3306/jmanne"
  DB_DRIVER = "com.mysql.jdbc.Driver"
  DB_MAX_CONNECTIONS = 5
 }     
}

JdbcConnectionPool.java

package com.jmanne.db;

import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.jmanne.utils.Configuration;
import com.mysql.jdbc.Connection;

public class JdbcConnectionPool {

 List<connection> availableConnections = new ArrayList<connection>();

 public JdbcConnectionPool()
 {
  initializeConnectionPool();
 }

 private void initializeConnectionPool()
 {
  while(!checkIfConnectionPoolIsFull())
  {
   availableConnections.add(createNewConnectionForPool());
  }
 }

 private synchronized boolean checkIfConnectionPoolIsFull()
 {
  final int MAX_POOL_SIZE = Configuration.getInstance().DB_MAX_CONNECTIONS;

  if(availableConnections.size() < MAX_POOL_SIZE)
  {
   return false;
  }

  return true;
 }

 //Creating a connection
 private Connection createNewConnectionForPool()
 {
  Configuration config = Configuration.getInstance();
  try {
   Class.forName(config.DB_DRIVER);
   Connection connection = (Connection) DriverManager.getConnection(
     config.DB_URL, config.DB_USER_NAME, config.DB_PASSWORD);
   return connection;
  } catch (ClassNotFoundException e) {
   e.printStackTrace();
  } catch (SQLException e) {
   e.printStackTrace();
  }
  return null;

 }

 public synchronized Connection getConnectionFromPool()
 {
  Connection connection = null;
  if(availableConnections.size() > 0)
  {
   connection = (Connection) availableConnections.get(0);
   availableConnections.remove(0);
  }
  return connection;
 }

 public synchronized void returnConnectionToPool(Connection connection)
 {
  availableConnections.add(connection);
 }
}

DataSource.java

package com.jmanne.db;

import java.sql.SQLException;

import com.mysql.jdbc.Connection;

public class DataSource {

 static JdbcConnectionPool pool = new JdbcConnectionPool();

 public static Connection getConnection() throws ClassNotFoundException, SQLException{
  Connection connection = pool.getConnectionFromPool();
  return connection;
 }

 public static void returnConnection(Connection connection) {
  pool.returnConnectionToPool(connection);
 }
}

Ответ 4

Просто используйте Семафоры. В идеале вы должны использовать CP3O или DBCP как пул соединений. Теперь вы можете активировать соединение, основанное на Семафоре.

Каждый раз, когда вы делаете Get, вы получаете и на каждом Release вы отпускаете его из Семафора. Более семафоров являются потокобезопасными.

Ответ 5

Используйте один из существующих, например. Apache DBCP

Соединения, возвращаемые пулом, часто являются прокси-серверами, которые "игнорируют" вызов close() из приложения. Когда соединения возвращаются в пул, их можно использовать повторно. При необходимости пулы также закрываются и автоматически открываются.

Ответ 6

Если ваше приложение запускается на сервере, то настройте его как источник данных, где сервер позаботится о пуле, или если простой клиент Java затем использует Apache DBCP (если в базе данных) или же использует API-интерфейс Apache Commons Pooling API См. Здесь: Apache Commons

Ответ 7

Одним из аргументов для сворачивания вашего собственного connpool является конфигурация и дополнительные банки, которых можно избежать. Я согласен, что вам нужно включить сторонние интерфейсы, чтобы вы могли поменяться местами в зрелом коннепсе, но иметь собственное крошечное решение может иметь свое место. Самоочищающийся вектор с синхронизированным блоком и оболочкой conn с тегом close(), который подходит для подключения, доступен для приложений сервлета.

Ответ 8

У меня есть одно решение для того же, чтобы создать утилиту пула соединений, которая может помочь вам создать пул размера по умолчанию 10.

@Component открытый класс ConnectionPool {приватный статический финал Logger logger = LoggerFactory.getLogger(ConnectionPool.class); приватный статический финал int MAX_POOL_SIZE_LIMIT = 10; private BlockingQueue activeConnectinoQueue = new LinkedBlockingQueue <>(); private BlockingQueue usedConnectinoList = new LinkedBlockingQueue <>(); private int initialPoolSize = 5;

@Autowired
@Qualifier("dataSource")
private DataSource dataSource;

public void initConnectionPool() {
    logger.info("ConnectionPool initialization started.");
    if(activeConnectinoQueue.isEmpty() && usedConnectinoList.isEmpty()) {
        for (int i=0; i<initialPoolSize; i++) {
            createConnections();
        }
    }
    logger.info("ConnectionPool initialization completed. ConnectionPool size : {}", activeConnectinoQueue.size());
}

private void createConnections() {
    try {
        Connection connection = dataSource.getConnection();
        activeConnectinoQueue.add(connection);
    }catch (SQLException e) {
        logger.error("Error in getting connection from pool : ", e);
    }
}

public Connection getConnection() {
    if(activeConnectinoQueue.isEmpty()) {
        initConnectionPool();
    }
    Connection connection =  activeConnectinoQueue.remove();

    try {
        if(connection.isClosed()) {
            connection = dataSource.getConnection();
        }
    }catch (SQLException e) {
        logger.error("Error while getting connection from pool : ", e);
    }

    usedConnectinoList.add(connection);
    return connection;
}


public void releaseConnection(Connection connection) {
    if(connection != null) {
        usedConnectinoList.remove(connection);
        activeConnectinoQueue.add(connection);
    }
}

public void setInitialPoolSize(int initialPoolSize) {
    if(!(initialPoolSize < 0 || initialPoolSize > MAX_POOL_SIZE_LIMIT)) {
        this.initialPoolSize = initialPoolSize;
    }
}

public int getInitialPoolSize() {
    return initialPoolSize;
}

public int getConnectionPoolSize() {
    return activeConnectinoQueue.size() + usedConnectinoList.size();
}

public void setDataSource(AbstractDataSource dataSource) {
    this.dataSource = dataSource;
}

public void closeConnectionPool() {

    logger.info("Closing connectionPool started.");
    close(usedConnectinoList);
    close(activeConnectinoQueue);
    logger.info("ConnectionPool Closed.");
}

private void close(BlockingQueue<Connection> connectinosQueue) {
    for (int i=0; i<connectinosQueue.size(); i++) {
        Connection connection = connectinosQueue.remove();
        if(connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                logger.error("Error in initializing connection pool : ", e);
            }
        }
    }
}

}

Теперь, чтобы сделать его безопасным, нам нужно прикрепить заводской объект..

public enum ConnectionFactory {
CONNECTION;

private ConnectionPool connectionPool;
public void setConnectionPool(ConnectionPool connectionPool) {
    this.connectionPool = connectionPool;
}

public Connection getConnection() {
    return connectionPool.getConnection();
}

public void closeConnection() {
    connectionPool.closeConnectionPool();
}

public void releaseConnection(Connection connection) {
    connectionPool.releaseConnection(connection);
}

public int getConnectionPoolSize() {
    return connectionPool.getConnectionPoolSize();
}

@Component
public static class ConnectionBuilder {
    @Autowired
    private ConnectionPool connectionPool;

    public void setConnectionPool(ConnectionPool connectionPool) {
        this.connectionPool = connectionPool;
    }
    @PostConstruct
    public void postConstruct() {
        for (ConnectionFactory cfactory : EnumSet.allOf(ConnectionFactory.class)) {
            cfactory.setConnectionPool(connectionPool);
        }
    }
}

}