Java为什么使用连接池
一、简介
动态 Web 站点往往用数据库存储的信息生成 Web 页面,每一个页面请求导致一次数据库访问。连接数据库不仅要开销一定的通信和内存资源,还必须完成用户验证、安全上下文配置这类任务,因为往往成为最为耗时的操作。
如果某个基于数据库的应用系统只需建立一次初始连接或者使用很少的打开、关闭数据库连接操作就可以完成工作,那么,系统的性能会得到显著的改善。实现这种思路的方法是:使多个请求能够共享同一个连接。连接池很好地满足了这样的要求,由连接池来管理数据连接的建立和注销,初始化时建立多条连接,以供客户使用。
用 JSP 开发 Web 应用系统,多数是基于数据库的程序,建立数据库连接的操作将是消耗系统资源最大的操作之一,如何减少这种开销,是开发人员应该首要关注的问题。
如何开发基于数据库的 Web 系统的传统模式:
1、在 JavaBeans 或者 Servlet 中建立数据库连接。
2、在页面 (JSP 等) 中调用 JavaBeans 获取连接,执行 Sql 操作并返回结果集。
3、断开数据库连接。
连接池技术:
由连接池来管理数据库连接的建立和注销。连接池初始化时建立多条连接,供给不同的请求使用,多个请求可以共享同一连接,这样做,就可以减少打开、关闭数据库连接的操作,从而改善了系统的性能。
二、连接池原理介绍
顾名思义,连接池最基本的思想就是预先建立一些连接放置于内存对象中以备使用。
一个连接池“拥有”一定数量的连接,当客户程序发出数据库连接请求时,连接池会从“池”中取出一个空闲的连接给客户程序,并将该连接状态设置成已占用;当客户程序使用完毕后,不会真正关闭这个连接,只是将其放回“池”中,同时将连接状态设置成空闲。如果“池”中没有空闲的连接,连接池可以根据某种策略自动地建立一个或多个连接,供后面的程序使用。
可见,连接的建立、断开以及一个池可以拥有的最大连接数都由连接池自身管理,客户程序可以不再关系这类事情,这样就实现了连接的共享,提供了 每个连接的利用效率。
三、设计思路
使用连接池的目的是想通过其自身的管理机制来管理数据库连接的状态和使用情况,包括管理连接池内连接的最大数、最小数、稳定数、连接时间、可用连接等等。因此,一个连接池管理类应该具有以下属性:
poolMaxSize: 最大连接数
poolSteadySize: 稳定大小
poolInitSize: 初始化大小
validPooledConnList: 容纳可用的缓冲数据库连接对象的容器——可用池
allPooledConnList: 所有的缓冲对象(可用的、不可用的)的容器——管理池
连接池的自由管理:静态管理、动态管理
静态管理:
静态管理是在客户程序发出请求时,连接池会检查各个连接的状态,并提供可用连接。运用连接池做一次连接的过程如下:
1. 初始化连接池,new 一定量的 connection.
2. 客户程序发出访问数据库的请求,连接池查找可用连接,如果找到,则直接返回一个连接。
3. 如果没有空闲连接,则重新 new 一个 connection 并且把它放到池里,然后返回这个 connection.
4. 如果连接池满了,程序是会停止 new 新的 connection,客户程序可以调用连接池的 release 方法释放掉旧的连接。
动态管理:通过一个线程定时地对每个连接的状态、连接的数量进行判断而进行相应的操作。
public class ConnectionPool { public boolean initialize() { //连接池的初始化 return true; }</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> destroy() { </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">连接池的销毁</span>
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">synchronized</span><span style="color: rgba(0, 0, 0, 1)"> PoolConn getConnection() { </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取一个连接</span>
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">synchronized</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> close() { </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">关闭一个连接</span>
}
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">synchronized</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> removeFormPool() { </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">把一个连接从连接池中移除</span>
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">synchronized</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> packPool() { </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">维护连接池的大小</span>
}
}
通过这几个方法,已经可以完成连接池的基本管理。因为我们要保存每一个连接的状态,所以还需要一个数据库连接对象:
class ConnObject { private java.sql.Connection conn; public java.sql.Connection getConn() {} </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> closeConn() { }
}
这样,在连接池中操作的连接对象是 ConnObject,当其他程序访问数据库时需要的只是 ConnObject 的 conn 属性,因为我们再加入一个类,封装这个实际的数据库连接对象,作为其他程序获得和释放数据库连接的方法。
class ConnBean { public java.sql.Connection getConnection();//从连接池中取出一个有效的连接 public void releaseConnection();//释放连接,此时并没有关闭连接,只是将连接放回连接池中<span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setConnection(java.sql.Connection conn); </span><span style="color: rgba(0, 0, 255, 1)">void</span> destroyPool();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">销毁连接池</span>
}