【问题标题】:Java Connection Pool implementationJava 连接池实现
【发布时间】:2012-05-18 19:39:59
【问题描述】:

你能看看我的连接池是否有可能实现它?

public class ConnectionPool {
    private static List<DBConnection> pool = null;
    private static int available = 0;
    private ConnectionPool() {}

    public static DBConnection getConnection() {
        if (pool == null) {
             pool = new ArrayList<DBConnection>();
             for (int i = 0; i < 3; i++) {
                 try {
                    pool.add(new DBConnection());
                    available++;
                } catch (SQLException e) {
                    e.printStackTrace();
                }
             }
        }
        if (pool.size() > 0) {
            available--;
            return pool.remove(available);
        } else {
            return null;
        }
    }

    public static void returnConnection(DBConnection c) {
        pool.add(c);
        available++;
    }
}

我只使用了一个数组,客户端应该向连接池请求一个连接使用它,然后将它返回给连接池。

  Connection connection = ConnectionPool.getConnection();
  connection.execute("insert into users values('"+user.getUsername()+"', '"+user.getPassword()+"', '"+user.getGroup()+"', '"+banned+"', '"+broker+admin+sharehodler+company+"')");      
  ConnectionPool.returnConnection(connection);
  connection = null;

我需要有关此实施的反馈。谢谢

【问题讨论】:

  • 为什么要重新发明轮子。有许多经过充分测试和验证的连接池实现可用。
  • 你为什么要这样做? javax.sql.DataSource 如果供应商已经实现了连接池,他们已经实现了连接池,并且在 Apache Commons 中也有一个很好的。
  • 目的是学习和理解连接池设计模式
  • 好的目的。但是,您可以从阅读现有实现的代码开始,而不是实现自己的连接池。例如。 svn.apache.org/viewvc/commons/proper/dbcp/trunk

标签: java database object connection pool


【解决方案1】:

一些想法:

  • 您的代码不是线程安全的。也许可以解决这个问题。
  • getConnection() 中的代码过多。真的是懒惰初始化吗 需要吗?
  • available 没用,可以用 pool.size() 代替。

【讨论】:

    【解决方案2】:

    有些地方使这个实现非常有问题。

    • 线程安全。如果多个线程与池一起工作怎么办?您没有锁定列表的读/写访问权限。
    • 静态最大池大小为 3 个连接,您也可以立即创建所有连接,无论它们是否需要。一种常见的策略是创建一堆连接并在需要时创建更多连接,直到达到允许/配置的最大值。
    • 您只有静态方法。应该可以有多个池,这意味着您需要 ConnectionPool 的实例。
    • 无法将 host+dbname+user+password 传递给创建的连接。
    • 您无需处理“断开”的连接 - 如果现有连接出现问题,您可能必须重新创建连接。这比我开始使用池之前所想的要重要得多。
    • 使用配置值而不是静态值,参见第 2 点
    • 最后:当然,自己编写这些东西很有趣 - 但如果您需要一个项目池,请选择一个现有的池,例如 c3p0tomcat connection pool

    我确信还有更多需要指出的地方,但除非这些都得到解决,否则继续下去是没有用的。

    【讨论】:

      【解决方案3】:

      阿法伊克,

      • 您的 getConnection() 方法需要更改为才能仅检索 Connection 对象。

        准备连接和池应从 getConnection() 方法中删除,并以这样的方式添加,以便在第一次加载 ConnectionPool 类时。

        您还需要处理一些其他属性以及connection timeoutpurging 等,以使其适用于所有场景。

        使其线程安全。

      【讨论】:

        【解决方案4】:

        池实现的一个大问题是您将裸连接传递给池的调用者。这意味着有人可以从您的池中获取连接,将其关闭,然后将其返回到池中。这不好

        解决这个问题的正常方法是使用委托包装返回的连接对象,并让它们忽略对 close 方法的调用(或者更好的是,让 close() 安全地将底层连接返回到池中)。

        其他主要问题:

        • 如果在事务中间返回连接会怎样?
        • 如果连接以某种方式损坏或断开,会发生什么情况?它会留在游泳池里吗?

        总而言之,您应该重用现有的连接池实现,而不是自己编写。如今,许多 4 类驱动程序都将自己的连接池包含在驱动程序中。

        【讨论】:

          【解决方案5】:

          其他成员已经提出了很多建议。我有一些模型实现,想分享给新访客。这是代码:

          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) {
                              // TODO Auto-generated catch block
                              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
            • 2020-11-01
            • 1970-01-01
            • 2015-04-28
            • 2016-05-24
            • 1970-01-01
            • 2013-04-08
            • 2015-08-07
            • 1970-01-01
            相关资源
            最近更新 更多