日期:2014-05-16 浏览次数:20486 次
在服务器端涉及数据库访问的应用程序里头,数据库连接池是一项确保性能的关键技术。一谈起java数据库连接池,大家都可以罗列出一堆开源实现。
它们也各有优劣:
1. DBCP TOMCAT自带的
2. proxool
3. c3p0: see: http://sourceforge.net/projects/c3p0
4. DBPool
5. Taobao的druid
这些都是蛮不错的连接池实现。基于不用重复造轮子一说,完全可以挑一个自己喜欢的去用。已有的轮子如果没出问题,还好说,出了问题,往往很难解决。
本文的主旨是阐述连接池的基本思想:
1. 能将池化的资源(连接)控制在一定范围以内[min, max]
2. 能在jvm退出之前,释放这些连接资源
3. 能尽量简化用户的代码
4. 能确保连接池的连接始终是活跃的
下面还是上代码吧, 以下的代码是整理而成,缺点还是不少,但是也足够一般情况下的使用,至少是可控的。
1. 一个hook类,用于jvm退出前释放资源
package com.hisql; import java.sql.SQLException; import org.apache.log4j.Logger; public class ReleasePoolHook implements Runnable { public static final Logger logger = Logger.getLogger(ReleasePoolHook.class); ConnectionPool connpool; public ReleasePoolHook(ConnectionPool pool) { // register it connpool = pool; Runtime.getRuntime().addShutdownHook(new Thread(this)); logger.info(">>> shutdown hook registered..."); } @Override public void run() { // TODO Auto-generated method stub logger.info("\n>>> About to execute: " + ReleasePoolHook.class.getName() + ".run() to clean up before JVM exits."); this.cleanUp(); logger.info(">>> Finished execution: " + ReleasePoolHook.class.getName() + ".run()"); } private void cleanUp() { if (connpool != null) { try { connpool.closeConnectionPool(); logger.info("Pool realeased...."); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); logger.warn("Pool released with exception", e); } } } }
package com.hisql; import java.sql.Connection; public class PooledConnection { Connection connection = null; boolean busy = false; public PooledConnection(Connection connection) { this.connection = connection; } public Connection getConnection() { return connection; } public void setConnection(Connection connection) { this.connection = connection; } public boolean isBusy() { return busy; } public void setBusy(boolean busy) { this.busy = busy; } }
这是主体实现类:
package com.hisql; import java.sql.*; import java.util.*; import org.apache.log4j.Logger; public class ConnectionPool { private String jdbcDriver; private String dbUrl; private String dbUsername; private String dbPassword; private String pingSql = "select 1"; // the test sql statement to ping the target database private int minConnections = 5; private int incrementalConnections = 2; private int maxConnections = 20; private Vector<PooledConnection> connections; private ReleasePoolHook hook; public static final Logger logger = Logger.getLogger(ConnectionPool.class); public ConnectionPool(String driver, String url, String username, String password) { jdbcDriver = driver; dbUrl = url; dbUsername = username; dbPassword = password; hook = new ReleasePoolHook(this); } public int getInitialConnections() { return this.minConnections; } public void setInitialConnections(int initialConnections) { this.minConnections = initialConnections; } public int getIncrement