JAVA数据库连接池实现(转)
连接池的管理用了了享元模式,这里对连接池进行简单设计。
一、设计思路
1.连接池配置属性DBbean:里面存放可以配置的一些属性
2.连接池接口IConnectionPool:里面定义一些基本的获取连接的一些方法
3.接口实现ConnectionPool:对上面操作进行实现,并加入一些其他方法
4.连接池管理ConnectionPoolManager:管理所有的不同的连接池,所有的连接都能通过这里进行获得连接
5.另外还有几个测试类,和连接信息模拟的类,这里就不进行xml 和配置文件信息的读取了
- package pool;
- /**
- * 这是外部可以配置的连接池属性
- * 可以允许外部配置,拥有默认值
- * @author Ran
- *
- */
- public class DBbean {
- // 连接池属性
- private String driverName;
- private String url;
- private String userName;
- private String password;
- // 连接池名字
- private String poolName;
- private int minConnections = 1; // 空闲池,最小连接数
- private int maxConnections = 10; // 空闲池,最大连接数
- private int initConnections = 5;// 初始化连接数
- private long connTimeOut = 1000;// 重复获得连接的频率
- private int maxActiveConnections = 100;// 最大允许的连接数,和数据库对应
- private long connectionTimeOut = 1000*60*20;// 连接超时时间,默认20分钟
- private boolean isCurrentConnection = true; // 是否获得当前连接,默认true
- private boolean isCheakPool = true; // 是否定时检查连接池
- private long lazyCheck = 1000*60*60;// 延迟多少时间后开始 检查
- private long periodCheck = 1000*60*60;// 检查频率
- public DBbean(String driverName, String url, String userName,
- String password, String poolName) {
- super();
- this.driverName = driverName;
- this.url = url;
- this.userName = userName;
- this.password = password;
- this.poolName = poolName;
- }
- public DBbean() {
- }
- public String getDriverName() {
- if(driverName == null){
- driverName = this.getDriverName()+"_"+this.getUrl();
- }
- return driverName;
- }
- public void setDriverName(String driverName) {
- this.driverName = driverName;
- }
- public String getUrl() {
- return url;
- }
- public void setUrl(String url) {
- this.url = url;
- }
- public String getUserName() {
- return userName;
- }
- public void setUserName(String userName) {
- this.userName = userName;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- public String getPoolName() {
- return poolName;
- }
- public void setPoolName(String poolName) {
- this.poolName = poolName;
- }
- public int getMinConnections() {
- return minConnections;
- }
- public void setMinConnections(int minConnections) {
- this.minConnections = minConnections;
- }
- public int getMaxConnections() {
- return maxConnections;
- }
- public void setMaxConnections(int maxConnections) {
- this.maxConnections = maxConnections;
- }
- public int getInitConnections() {
- return initConnections;
- }
- public void setInitConnections(int initConnections) {
- this.initConnections = initConnections;
- }
- public int getMaxActiveConnections() {
- return maxActiveConnections;
- }
- public void setMaxActiveConnections(int maxActiveConnections) {
- this.maxActiveConnections = maxActiveConnections;
- }
- public long getConnTimeOut() {
- return connTimeOut;
- }
- public void setConnTimeOut(long connTimeOut) {
- this.connTimeOut = connTimeOut;
- }
- public long getConnectionTimeOut() {
- return connectionTimeOut;
- }
- public void setConnectionTimeOut(long connectionTimeOut) {
- this.connectionTimeOut = connectionTimeOut;
- }
- public boolean isCurrentConnection() {
- return isCurrentConnection;
- }
- public void setCurrentConnection(boolean isCurrentConnection) {
- this.isCurrentConnection = isCurrentConnection;
- }
- public long getLazyCheck() {
- return lazyCheck;
- }
- public void setLazyCheck(long lazyCheck) {
- this.lazyCheck = lazyCheck;
- }
- public long getPeriodCheck() {
- return periodCheck;
- }
- public void setPeriodCheck(long periodCheck) {
- this.periodCheck = periodCheck;
- }
- public boolean isCheakPool() {
- return isCheakPool;
- }
- public void setCheakPool(boolean isCheakPool) {
- this.isCheakPool = isCheakPool;
- }
- }
- package pool;
- import java.sql.Connection;
- import java.sql.SQLException;
- public interface IConnectionPool {
- // 获得连接
- public Connection getConnection();
- // 获得当前连接
- public Connection getCurrentConnecton();
- // 回收连接
- public void releaseConn(Connection conn) throws SQLException;
- // 销毁清空
- public void destroy();
- // 连接池是活动状态
- public boolean isActive();
- // 定时器,检查连接池
- public void cheackPool();
- }
- package pool;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.SQLException;
- import java.util.List;
- import java.util.Timer;
- import java.util.TimerTask;
- import java.util.Vector;
- public class ConnectionPool implements IConnectionPool {
- // 连接池配置属性
- private DBbean dbBean;
- private boolean isActive = false; // 连接池活动状态
- private int contActive = 0;// 记录创建的总的连接数
- // 空闲连接
- private List<Connection> freeConnection = new Vector<Connection>();
- // 活动连接
- private List<Connection> activeConnection = new Vector<Connection>();
- // 将线程和连接绑定,保证事务能统一执行
- private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
- public ConnectionPool(DBbean dbBean) {
- super();
- this.dbBean = dbBean;
- init();
- cheackPool();
- }
- // 初始化
- public void init() {
- try {
- Class.forName(dbBean.getDriverName());
- for (int i = 0; i < dbBean.getInitConnections(); i++) {
- Connection conn;
- conn = newConnection();
- // 初始化最小连接数
- if (conn != null) {
- freeConnection.add(conn);
- contActive++;
- }
- }
- isActive = true;
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- // 获得当前连接
- public Connection getCurrentConnecton(){
- // 默认线程里面取
- Connection conn = threadLocal.get();
- if(!isValid(conn)){
- conn = getConnection();
- }
- return conn;
- }
- // 获得连接
- public synchronized Connection getConnection() {
- Connection conn = null;
- try {
- // 判断是否超过最大连接数限制
- if(contActive < this.dbBean.getMaxActiveConnections()){
- if (freeConnection.size() > 0) {
- conn = freeConnection.get(0);
- if (conn != null) {
- threadLocal.set(conn);
- }
- freeConnection.remove(0);
- } else {
- conn = newConnection();
- }
- }else{
- // 继续获得连接,直到从新获得连接
- wait(this.dbBean.getConnTimeOut());
- conn = getConnection();
- }
- if (isValid(conn)) {
- activeConnection.add(conn);
- contActive ++;
- }
- } catch (SQLException e) {
- e.printStackTrace();
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- return conn;
- }
- // 获得新连接
- private synchronized Connection newConnection()
- throws ClassNotFoundException, SQLException {
- Connection conn = null;
- if (dbBean != null) {
- Class.forName(dbBean.getDriverName());
- conn = DriverManager.getConnection(dbBean.getUrl(),
- dbBean.getUserName(), dbBean.getPassword());
- }
- return conn;
- }
- // 释放连接
- public synchronized void releaseConn(Connection conn) throws SQLException {
- if (isValid(conn)&& !(freeConnection.size() > dbBean.getMaxConnections())) {
- freeConnection.add(conn);
- activeConnection.remove(conn);
- contActive --;
- threadLocal.remove();
- // 唤醒所有正待等待的线程,去抢连接
- notifyAll();
- }
- }
- // 判断连接是否可用
- private boolean isValid(Connection conn) {
- try {
- if (conn == null || conn.isClosed()) {
- return false;
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return true;
- }
- // 销毁连接池
- public synchronized void destroy() {
- for (Connection conn : freeConnection) {
- try {
- if (isValid(conn)) {
- conn.close();
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- for (Connection conn : activeConnection) {
- try {
- if (isValid(conn)) {
- conn.close();
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- isActive = false;
- contActive = 0;
- }
- // 连接池状态
- @Override
- public boolean isActive() {
- return isActive;
- }
- // 定时检查连接池情况
- @Override
- public void cheackPool() {
- if(dbBean.isCheakPool()){
- new Timer().schedule(new TimerTask() {
- @Override
- public void run() {
- // 1.对线程里面的连接状态
- // 2.连接池最小 最大连接数
- // 3.其他状态进行检查,因为这里还需要写几个线程管理的类,暂时就不添加了
- System.out.println("空线池连接数:"+freeConnection.size());
- System.out.println("活动连接数::"+activeConnection.size());
- System.out.println("总的连接数:"+contActive);
- }
- },dbBean.getLazyCheck(),dbBean.getPeriodCheck());
- }
- }
- }
- package pool;
- import java.sql.Connection;
- import java.sql.SQLException;
- import java.util.Hashtable;
- /**
- * 连接管理类
- * @author Ran
- *
- */
- public class ConnectionPoolManager {
- // 连接池存放
- public Hashtable<String,IConnectionPool> pools = new Hashtable<String, IConnectionPool>();
- // 初始化
- private ConnectionPoolManager(){
- init();
- }
- // 单例实现
- public static ConnectionPoolManager getInstance(){
- return Singtonle.instance;
- }
- private static class Singtonle {
- private static ConnectionPoolManager instance = new ConnectionPoolManager();
- }
- // 初始化所有的连接池
- public void init(){
- for(int i =0;i<DBInitInfo.beans.size();i++){
- DBbean bean = DBInitInfo.beans.get(i);
- ConnectionPool pool = new ConnectionPool(bean);
- if(pool != null){
- pools.put(bean.getPoolName(), pool);
- System.out.println("Info:Init connection successed ->" +bean.getPoolName());
- }
- }
- }
- // 获得连接,根据连接池名字 获得连接
- public Connection getConnection(String poolName){
- Connection conn = null;
- if(pools.size()>0 && pools.containsKey(poolName)){
- conn = getPool(poolName).getConnection();
- }else{
- System.out.println("Error:Can't find this connecion pool ->"+poolName);
- }
- return conn;
- }
- // 关闭,回收连接
- public void close(String poolName,Connection conn){
- IConnectionPool pool = getPool(poolName);
- try {
- if(pool != null){
- pool.releaseConn(conn);
- }
- } catch (SQLException e) {
- System.out.println("连接池已经销毁");
- e.printStackTrace();
- }
- }
- // 清空连接池
- public void destroy(String poolName){
- IConnectionPool pool = getPool(poolName);
- if(pool != null){
- pool.destroy();
- }
- }
- // 获得连接池
- public IConnectionPool getPool(String poolName){
- IConnectionPool pool = null;
- if(pools.size() > 0){
- pool = pools.get(poolName);
- }
- return pool;
- }
- }
- package pool;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * 初始化,模拟加载所有的配置文件
- * @author Ran
- *
- */
- public class DBInitInfo {
- public static List<DBbean> beans = null;
- static{
- beans = new ArrayList<DBbean>();
- // 这里数据 可以从xml 等配置文件进行获取
- // 为了测试,这里我直接写死
- DBbean beanOracle = new DBbean();
- beanOracle.setDriverName("oracle.jdbc.driver.OracleDriver");
- beanOracle.setUrl("jdbc:oracle:thin:@7MEXGLUY95W1Y56:1521:orcl");
- beanOracle.setUserName("mmsoa");
- beanOracle.setPassword("password1234");
- beanOracle.setMinConnections(5);
- beanOracle.setMaxConnections(100);
- beanOracle.setPoolName("testPool");
- beans.add(beanOracle);
- }
- }
测试:
- package pool;
- import java.sql.Connection;
- /**
- * 模拟线程启动,去获得连接
- * @author Ran
- *
- */
- public class ThreadConnection implements Runnable{
- private IConnectionPool pool;
- @Override
- public void run() {
- pool = ConnectionPoolManager.getInstance().getPool("testPool");
- }
- public Connection getConnection(){
- Connection conn = null;
- if(pool != null && pool.isActive()){
- conn = pool.getConnection();
- }
- return conn;
- }
- public Connection getCurrentConnection(){
- Connection conn = null;
- if(pool != null && pool.isActive()){
- conn = pool.getCurrentConnecton();
- }
- return conn;
- }
- }
- package pool;
- public class Client {
- public static void main(String[] args) throws InterruptedException {
- // 初始化连接池
- Thread t = init();
- t.start();
- t.join();
- ThreadConnection a = new ThreadConnection();
- ThreadConnection b = new ThreadConnection();
- ThreadConnection c = new ThreadConnection();
- Thread t1 = new Thread(a);
- Thread t2 = new Thread(b);
- Thread t3 = new Thread(c);
- // 设置优先级,先让初始化执行,模拟 线程池 先启动
- // 这里仅仅表面控制了,因为即使t 线程先启动,也不能保证pool 初始化完成,为了简单模拟,这里先这样写了
- t1.setPriority(10);
- t2.setPriority(10);
- t3.setPriority(10);
- t1.start();
- t2.start();
- t3.start();
- System.out.println("线程A-> "+a.getConnection());
- System.out.println("线程B-> "+b.getConnection());
- System.out.println("线程C-> "+c.getConnection());
- }
- // 初始化
- public static Thread init() {
- Thread t = new Thread(new Runnable() {
- @Override
- public void run() {
- IConnectionPool pool = initPool();
- while(pool == null || !pool.isActive()){
- pool = initPool();
- }
- }
- });
- return t;
- }
- public static IConnectionPool initPool(){
- return ConnectionPoolManager.getInstance().getPool("testPool");
- }
- }
小结 :
1.连接池诞生原因是,如果每次都从数据库获得连接,时间比较长,因此我们提前做建立一些连接,放在连接池里面,每次都从里面取
2.上面仅仅写了连接池基本原理,关于多线程下连接池的管理没写,后面对多线程操作熟练了添加吧
本文转自http://greemranqq.iteye.com/blog/1969273 感谢作者
JAVA数据库连接池实现(转)的更多相关文章
- Java数据库连接池封装与用法
Java数据库连接池封装与用法 修改于抄袭版本,那货写的有点BUG,两个类,一个用法 ConnectionPool类: package com.vl.sql; import java.sql.Conn ...
- Java数据库连接池
转载过来的,最近在做一个小网站,准备使用这种方法. Java jdbc数据库连接池总结! 1. 引言 近年来,随着Internet/Intranet建网技术的飞速发展和在世界范围内的迅速普及, ...
- 一个JAVA数据库连接池实现源码
原文链接:http://www.open-open.com/lib/view/open1410875608164.html // // 一个效果非常不错的JAVA数据库连接池. // from:htt ...
- Java数据库连接池的几种配置方法(以MySQL数据库为例)
Java数据库连接池的几种配置方法(以MySQL数据库为例) 一.Tomcat配置数据源: 前提:需要将连接MySQL数据库驱动jar包放进Tomcat安装目录中common文件夹下的lib目录中 1 ...
- Java数据库连接池详解
http://www.javaweb1024.com/java/JavaWebzhongji/2015/06/01/736.html 对于共享资源,有一个很著名的设计模式:资源池(Resource P ...
- 主流Java数据库连接池分析(C3P0,DBCP,TomcatPool,BoneCP,Druid)
主流数据库连接池 常用的主流开源数据库连接池有C3P0.DBCP.Tomcat Jdbc Pool.BoneCP.Druid等 C3p0: 开源的JDBC连接池,实现了数据源和JNDI绑定,支持JDB ...
- [转帖]为什么HikariCP被号称为性能最好的Java数据库连接池,如何配置使用
为什么HikariCP被号称为性能最好的Java数据库连接池,如何配置使用 原创Clement-Xu 发布于2015-07-17 15:53:14 阅读数 57066 收藏 展开 HiKariCP是 ...
- 从零开始学 Java - 数据库连接池的选择 Druid
我先说说数据库连接 数据库大家都不陌生,从名字就能看出来它是「存放数据的仓库」,那我们怎么去「仓库」取东西呢?当然需要钥匙啦!这就是我们的数据库用户名.密码了,然后我们就可以打开门去任意的存取东西了. ...
- java数据库连接池技术原理(浅析)
在执行数据库SQL语句时,我们先要进行数据连接:而每次创建新的数据库的连接要消耗大量的资源,这样,大家就想出了数据库连接池技术.它的原理是,在运行过程中,同时打开着一定数量的数据库连接,形成数据连接池 ...
- [数据库连接池二]Java数据库连接池--C3P0和JDNI.
前言:上一篇文章中讲了DBCP的用法以及实现原理, 这一篇再来说下C3P0和JDNI的用法. 1.1.C3P0数据源 C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规 ...
随机推荐
- EF6 在原有数据库中使用 CodeFirst 总复习(二、新的需求,简单修改原有表)
一.为当前实体模型启用数据迁移 基础搭建好了,也就是原有的数据库有了,原有数据库的实体对象也有了,但生成的上下文中并没有标记当前数据库是否已经存在,当前实体是否修改过(以前版本好像有标记的),所以,要 ...
- 在本地环境用虚拟机win2008 sever搭建VS2013 + SVN 代码版本控制环境
此文仅仅是自己笔记做个备忘.因为自己开发一些中小型的软件经常需要修修改改,特别是winform界面的大改动.经常需要对版本进行管理.而租用分布式服务器和远程服务器都不是自己想要的.本文结合虚拟机 + ...
- 闹钟类app构想
NABC--闹钟app N:我们打算针对那些易健忘的人来制作一款闹钟功能的记事本,具来说服务的对象有很多:有健忘的人,还有情侣,北漂的人及其父母(...),常年见不到亲人(双方),后期我们若提前完成基 ...
- 基于OpenMP的矩阵乘法实现及效率提升分析
一. 矩阵乘法串行实现 例子选择两个1024*1024的矩阵相乘,根据矩阵乘法运算得到运算结果.其中,两个矩阵中的数为double类型,初值由随机数函数产生.代码如下: #include <i ...
- Entity Framework 学习之--Ling to entity实现分页
最近用MVC做的一个项目涉及到分页,中间用了entity framework来查数据库,不用直接写sql语句,方便了很多. 一般分页的思路是获得两个变量的值: 1.一共有多少条记录 totalCoun ...
- Leetcode#135 Candy
原题地址 遍历所有小孩的分数 1. 若小孩的分数递增,分给小孩的糖果依次+12. 若小孩的分数递减,分给小孩的糖果依次-13. 若小孩的分数相等,分给小孩的糖果设为1 当递减序列结束时,如果少分了糖果 ...
- Leetcode#71 Simplify Path
原题地址 用栈保存化简后的路径.把原始路径根据"/"切分成若干小段,然后依次遍历 若当前小段是"..",弹栈 若当前小段是".",什么也不做 ...
- CentOS 有gcc没有g++
[root@localhost ~]# which gcc/usr/bin/gcc[root@localhost ~]# which g++/usr/bin/which: no g++ in (/us ...
- 贴代码—CF230 DIV1 B
题目在此: http://codeforces.com/contest/392/problem/B 一直理解错了一句话,以为是用最小的move求最小的花费, 读错题目的有木有!!! 不懂汉诺塔的原理有 ...
- [翻译]The Neophyte's Guide to Scala Part 12: Type Classes
The Neophyte's Guide to Scala Part 12: Type Classes 过去的两周我们讨论了一些使我们保持DRY和灵活性的函数式编程技术,特别是函数组合,partial ...