【问题标题】:Need Code to create Connection Pool in java需要代码在java中创建连接池
【发布时间】:2011-02-19 01:14:49
【问题描述】:

需要在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();
 }

}

【问题讨论】:

  • 不管下面的一些答案是什么,都写你自己的连接池。将您与周围的其他人进行比较,并在此过程中了解更多有关 JDBC 和其他内容的知识。仅仅拥有一堆成熟的产品不应该阻止你制作自己的产品。只需将它们视为要被击败的标准。去吧

标签: java connection connection-pooling


【解决方案1】:

使用现有的之一,例如Apache DBCP

池返回的连接通常是“忽略”应用程序对close() 的调用的代理。当连接返回到池中时,它们可以被重用。如有必要,游泳池也会自动关闭和重新打开。

【讨论】:

    【解决方案2】:

    需要在java中创建连接池的代码吗?

    不确定问题是什么,但不要创建另一个连接池,使用现有的解决方案,如 C3P0Apache DBCPProxoolBoneCP(该领域的新玩家)。我会使用 C3P0。

    我们如何确保连接池不会返回已在使用的同一个对象?

    因为如果一个连接已经从池中借用并且还没有返回,它只是不在池中并且不能分配给池的另一个客户端(资源被从池中移除直到它们被返回)。

    如果客户端从连接池中取出连接后关闭连接会怎样?

    客户端从池中获得的连接并不是真正的java.sql.Connection,它是java.sql.Connection 的包装器(代理),可自定义某些方法的行为。 close() 方法就是其中之一,它关闭 Connection 实例,而是将其返回到池中。

    【讨论】:

    • +1 for C3PO...我一直在使用它,效果非常好。它重量轻,非常易于使用。
    • “不关闭 Connection 实例,而是将其返回到池中” - 连接类如何知道池并在调用 close 方法时能够将自身返回到池中?
    • 请务必查看 Hikari CP:github.com/brettwooldridge/HikariCP。从我读到的,它似乎比列出的要快得多。
    【解决方案3】:

    如果您的应用程序在服务器上运行,则配置为数据源,服务器将负责池化,否则如果是简单的 Java 客户端,则使用 Apache DBCP(如果用于数据库)或使用 Apache Commons Pooling API 见这里:Apache Commons

    【讨论】:

      【解决方案4】:

      不要自己写。有很多库可以为您执行此操作,它们是开源且易于使用的,并且会解决您在尝试自己制作时遇到的所有问题。

      这是一个使用 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");
      

      一旦有了数据源,就很容易从池中获取连接。

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

      关闭连接会将其返回到池中。

      connection.close();
      

      【讨论】:

      • +1。但是,一个更正 - setDriverClassName() 和其他方法在 javax.sql.DataSource[java 1.6] 中不可用。类型应该是 BasicDataSource 。即:BasicDataSource source = new BasicDataSource(); 了解更多详情:svn.apache.org/viewvc/commons/proper/dbcp/trunk/doc/…
      • 不要自己写,使用现有的“不支持、取消支持、历史”库,什么也学不到。我不同意。为什么新开发者不应该自己写,至少应该支持他们自己实现,以便他们可以学习。为什么不? “编写你自己的,并使用编写良好的单元测试和文档编写”
      【解决方案5】:

      滚动您自己的 connpool 的一个参数是要避免的配置和其他 jar。我同意您需要启用 3rd 方接口,以便您可以在成熟的 connpool 中进行交换,但是拥有自己的微型解决方案可以占有一席之地。带有同步块的自清洁 Vector 和带有 close() 将 conn 标记为可用的 conn 包装器非常适用于 servlet 应用程序。

      【讨论】:

        【解决方案6】:

        只需使用信号量。理想情况下,您应该使用CP3ODBCP 作为连接池。现在您可以根据信号量限制您的连接。

        每次您执行Get 时,您都会从 Semaphore 中获取并在每次 Release 时释放它。更多信号量是线程安全的。

        【讨论】:

          【解决方案7】:

          我希望这个源代码有帮助 http://jagadeeshmanne.blogspot.com/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);
           }
          }
          

          【讨论】:

          • db驱动是什么意思?
          • 您能否举个例子来说明您将如何使用此代码?
          • 抱歉耽搁了。 db driver 表示驱动程序类名。需要将该变量名称更改为 driverClass。您可以在服务类中使用 DataSource.getConnection()。它将从池中返回连接对象
          【解决方案8】:

          我有一个相同的解决方案来创建一个连接池实用程序,它可以帮助您创建一个默认大小为 10 的池。

          @组件 公共类连接池 { private static final Logger logger = LoggerFactory.getLogger(ConnectionPool.class); 私有静态最终 int MAX_POOL_SIZE_LIMIT = 10; 私有 BlockingQueue activeConnectinoQueue = new LinkedBlockingQueue(); 私有阻塞队列 usedConnectinoList = new LinkedBlockingQueue(); 私有 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);
                  }
              }
          }
          

          }

          【讨论】:

            【解决方案9】:

            Java 连接池?
            有3种方式来创建JDBC Connection Pooling 很简单...

            1. Apache Commons DBCP

              public class DBCPDataSource {
              
              private static BasicDataSource ds = new BasicDataSource();
              
              static {
                  ds.setUrl("jdbc:h2:mem:test");
                  ds.setUsername("user");
                  ds.setPassword("password");
                  ds.setMinIdle(5);
                  ds.setMaxIdle(10);
                  ds.setMaxOpenPreparedStatements(100);
              }
              
              public static Connection getConnection() throws SQLException {
                  return ds.getConnection();
              }
              
              private DBCPDataSource(){ }
              }
              

              现在可以连接了

              Connection con = DBCPDataSource.getConnection();
              
            2. HikariCP

              public class HikariCPDataSource {
              
              private static HikariConfig config = new HikariConfig();
              private static HikariDataSource ds;
              
              static {
                  config.setJdbcUrl("jdbc:h2:mem:test");
                  config.setUsername("user");
                  config.setPassword("password");
                  config.addDataSourceProperty("cachePrepStmts", "true");
                  config.addDataSourceProperty("prepStmtCacheSize", "250");
                  config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
                  ds = new HikariDataSource(config);
              }
              
              public static Connection getConnection() throws SQLException {
                  return ds.getConnection();
              }
              
              private HikariCPDataSource(){}
              }
              

            现在可以连接了

            Connection con = HikariCPDataSource.getConnection();
            
            1. C3PO

               public class C3poDataSource {
              
              private static ComboPooledDataSource cpds = new ComboPooledDataSource();
              
              static {
                  try {
                      cpds.setDriverClass("org.h2.Driver");
                      cpds.setJdbcUrl("jdbc:h2:mem:test");
                      cpds.setUser("user");
                      cpds.setPassword("password");
                  } catch (PropertyVetoException e) {
                      // handle the exception
                  }
              }
              
              public static Connection getConnection() throws SQLException {
                  return cpds.getConnection();
              }
              
              private C3poDataSource(){}
              }
              

            现在可以连接了

            Connection con = C3poDataSource.getConnection();
            

            【讨论】:

              【解决方案10】:

              我有一些 Java 模型代码,它具有多线程连接池。

              import java.sql.Connection;
              import java.sql.DriverManager;
              import java.sql.ResultSet;
              import java.sql.SQLException;
              import java.sql.Statement;
              import java.util.Iterator;
              import java.util.concurrent.ConcurrentLinkedQueue;
              import java.util.concurrent.ExecutorService;
              import java.util.concurrent.Executors;
              import java.util.concurrent.ScheduledExecutorService;
              import java.util.concurrent.TimeUnit;
              
              abstract class ObjectPool<T> {
                  private ConcurrentLinkedQueue<T> pool;
                  ScheduledExecutorService executorService;
              
                  ObjectPool(int minObjects) {
                      pool = new ConcurrentLinkedQueue<T>();
                      for (int i = 0; i < minObjects; i++) {
                          pool.add(createObject());
                      }
                  }
              
                  ObjectPool(final int minObjects, final int maxSize, final long interval){
                      pool = new ConcurrentLinkedQueue<T>();
                      for (int i = 0; i < minObjects; i++) {
                          pool.add(createObject());
                      }
              
                      executorService = Executors.newSingleThreadScheduledExecutor();
                      executorService.scheduleWithFixedDelay(new Runnable(){
              
                          public void run() {
                              int size = pool.size();
                              while(size > maxSize){
                                  pool.remove();
                              }
                              Iterator i = pool.iterator();
                              while(i.hasNext()){
                                  T t = (T) i.next();
                                  if(checkExpiry(t)){
                                      System.out.println("Expiry existed...");
                                      i.remove();
                                  }
                              }
              
                              while(pool.size() < minObjects){
                                  System.out.println("Adding more objects to pool");
                                  pool.add(createObject());
                              }
                          }
              
                      }, interval, interval, TimeUnit.MILLISECONDS);
              
                  }
              
                  public T borrowObject() {
                      if (pool.peek() == null)
                          return createObject();
                      return pool.remove();
                  }
              
                  public void addObject(T obj) {
                      if (obj == null)
                          return;
                      pool.add(obj);
                  }
              
                  public abstract T createObject();
              
                  public abstract boolean checkExpiry(T t);
              }
              
              class MultithreadQuery extends Thread{
                  private ObjectPool<Connection> pool;
                  private int threadNo;
                  String query;
                  MultithreadQuery(ObjectPool<Connection> pool,int threadNo, String query){
                      this.pool = pool;
                      this.threadNo = threadNo;
                      this.query = query;
              
                  }
                  @Override
                  public void run(){
                      Connection con = pool.borrowObject();
                      Statement stmt;
                      try {
                          stmt = con.createStatement();
                          System.out.println("Query started for thread->"+ threadNo);
                          ResultSet rs=stmt.executeQuery(query);
                          while(rs.next())  
                          System.out.println(rs.getInt(1)+"  "+rs.getString(2)+"  "+rs.getString(3));
                          System.out.println("closing connection....");
                          con.close();
                      } catch (SQLException e) {
                          // TODO Auto-generated catch block
                          e.printStackTrace();
                      }  
                      pool.addObject(con);        
                      System.out.println("Query ended for thread->"+ threadNo);
                  }
              }
              
              public class ObjectPoolPatternDemo {
                  ObjectPool<Connection> pool;
              
                  public void setUp(){
                      pool = new ObjectPool<Connection>(4, 10, 1) {
              
                          @Override
                          public Connection createObject() {
                              Connection con;
                              try {
                                  con = DriverManager.getConnection("URL","Username","Password");
                                  return con;
                              } catch (SQLException e) {
                                  e.printStackTrace();
                              }
                              return null;
                          }
              
                          @Override
                          public boolean checkExpiry(Connection conn) {
                              boolean expiryFlag = false;
                              try {
                                  if(conn.isClosed())
                                      expiryFlag = true;
              
                              } catch (SQLException e) {
                                  e.printStackTrace();
                              }
                              return expiryFlag;
                          }
                      };
                  }
              
                  public static void main(String[] args) throws SQLException {
                      ObjectPoolPatternDemo oppd = new ObjectPoolPatternDemo();
                      oppd.setUp();
              
                      ExecutorService es = Executors.newFixedThreadPool(4);
                      String query = "select * from TABLE";
                      es.execute(new MultithreadQuery(oppd.pool,1,query));
                      es.execute(new MultithreadQuery(oppd.pool,2,query));
                      es.execute(new MultithreadQuery(oppd.pool,3,query));
                      es.execute(new MultithreadQuery(oppd.pool,4,query));
                      es.execute(new MultithreadQuery(oppd.pool,5,query));
                      es.execute(new MultithreadQuery(oppd.pool,6,query));
              
                      es.shutdown();
                      try {
                          es.awaitTermination(1, TimeUnit.DAYS);
                      } catch (InterruptedException e) {
                          // TODO Auto-generated catch block
                          e.printStackTrace();
                      }
                      System.out.println("finally completed...");
                  }
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2013-10-01
                • 2019-03-28
                • 1970-01-01
                • 1970-01-01
                • 2011-10-15
                • 1970-01-01
                • 1970-01-01
                • 2017-07-23
                相关资源
                最近更新 更多