问题:在一个简单的JDBC操作中几乎50%以上的时间用于用户获取连接,而不是操作数据库
而实现连接的方法由各个数据库连接厂商提供驱动,要提高连接效率,问题在于获取连接以后,是否可以持续拥有这样的连接,当再有人需要连接时,将这个连接直接提供给他,而不是用完一次就关闭数据库连接!但此方法还有很多缺陷,例如:连接多次以后,连接是否稳定的问题,连接池的容量的大小问题,连接池高效利用问题...等等
注:该类方法适用于需要多次获得数据库连接。
解决方案:资源重用 --连接池
用户每次请求动需要向数据库获得连接,而数据创建连接通常需要消耗相对较大的资源,通过连接池共享连接,减少开关连接的次数,提高程序的效率
1、自定义连接池:(也可采用开源数据库连接池c3p0等)。注意:需要在使用完连接后记得不关闭连接,而是调用retrun conn方法将连接还回池中。
2、改造close 方法(继承或者代理模式)目的:将连接还回去,而不是关闭
连接池用于创建和管理数据库连接的缓冲池技术,缓冲池中的连接可以被任何需要他们的线程使用。当一个线程需要用JDBC对一个数据库操作时,将从池中请求一个连接。当这个连接使用完毕后,将返回到连接池中,等待为其他的线程服务。 连接池的主要优点有以下三个方面。
第一、减少连接创建时间。连接池中的连接是已准备好的、可重复使用的,获取后可以直接访问数据库,因此减少了连接创建的次数和时间。
第二、简化的编程模式。当使用连接池时,每一个单独的线程能够像创建一个自己的JDBC连接一样操作,允许用户直接使用JDBC编程技术。
第三、控制资源的使用。如果不使用连接池,每次访问数据库都需要创建一个连接,这样系统的稳定性受系统连接需求影响很大,很容易产生资源浪费和高负载异常。连接池能够使性能最大化,将资源利用控制在一定的水平之下。连接池能控制池中的连接数量,增强了系统在大量用户应用时的稳定性。
连接池的原理:
连接池技术的核心思想是连接复用,通过建立一个数据库连接池以及一套连接使用、分配和管理策略,使得该连接池中的连接可以得到高效、安全的复用,避免了数据库连接频繁建立、关闭的开销。
连接池的工作原理主要由三部分组成,分别为连接池的建立、连接池中连接的使用管理、连接池的关闭。
第一、连接池的建立。一般在系统初始化时,连接池会根据系统配置建立,并在池中创建了几个连接对象,以便使用时能从连接池中获取。连接池中的连接不能随意创建和关闭,这样避免了连接随意建立和关闭造成的系统开销。Java中提供了很多容器类可以方便的构建连接池,例如Vector、Stack等。
第二、连接池的管理。连接池管理策略是连接池机制的核心,连接池内连接的分配和释放对系统的性能有很大的影响。其管理策略是:
当客户请求数据库连接时,首先查看连接池中是否有空闲连接,如果存在空闲连接,则将连接分配给客户使用;如果没有空闲连接,则查看当前所开的连接数是否已经达到最大连接数,如果没达到就重新创建一个连接给请求的客户;如果达到就按设定的最大等待时间进行等待,如果超出最大等待时间,则抛出异常给客户。 当客户释放数据库连接时,先判断该连接的引用次数是否超过了规定值,如果超过就从连接池中删除该连接,否则保留为其他客户服务。该策略保证了数据库连接的有效复用,避免频繁的建立、释放连接所带来的系统资源开销。
第三、连接池的关闭。当应用程序退出时,关闭连接池中所有的连接,释放连接池相关的资源,该过程正好与创建相反。
具体代码如下:
public class lianJieChi {
private lianJieChi() {
}
private static final List<Connection> list = Collections
.synchronizedList(new ArrayList<Connection>());
private static final Properties pro = new Properties();
private static final int MAX_SIZE = 10;
// 静态语句块,类加载时,自动加载输入流,加载驱动
static {
try {
loadProperties();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 建立连接,设计模式
public static Connection getConnection() throws SQLException {
Connection conn = null;
//判断连接池(list集合)里面是否为空,为空时获取数据库连接
if (list.isEmpty()) {
String url = pro.getProperty("url");
String name = pro.getProperty("username");
String password = pro.getProperty("password");
return DriverManager.getConnection(url, name, password);
} else {
//否则就移除掉集合最后一位的连接
conn = list.remove(list.size() - 1);
}
return conn;
}
// 归还(关闭)连接数据库,当数据库的连接的数量大于设定的值MAX_SIZE时,关闭数据库
public static void closeConnection(Connection conn) throws SQLException {
if (conn != null) {
if (list.size() > MAX_SIZE) {
conn.close();
}
} else {
//否则就添加到集合,相当于归还连接。
list.add(conn);
}
}
// 输入流,加载驱动
private static void loadProperties() throws ClassNotFoundException {
if (pro.isEmpty()) {
InputStream is = lianJieChi.class
.getResourceAsStream("peizhi.Properties");
try {
pro.load(is);
String classname = pro.getProperty("driver");
Class.forName(classname);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
红包分享
钱包管理

