JAVA数据库连接池实现
博客分类:
• 数据库连接池
JAVA数据库连接池连接池原理连接池实现JAVA连接池
连接池的管理用了了享元模式,这里对连接池进行简单设计。
一、设计思路
1.连接池配置属性DBbean:里面存放可以配置的一些属性
2.连接池接口IConnectionPool:里面定义一些基本的获取连接的一些方法
3.接口实现ConnectionPool:对上面操作进行实现,并加入一些其他方法
4.连接池管理ConnectionPoolManager:管理所有的不同的连接池,所有的连接都能通过这里进行获得连接
5.另外还有几个测试类,和连接信息模拟的类,这里就不进行xml 和配置文件信息的读取了
Java代码


1.  package pool;
2.  /**
3.   * 这是外部可以配置的连接池属性
4.   * 可以允许外部配置,拥有默认值
5.   * @author Ran
6.   *
7.   */
8.  public class DBbean {
9.      // 连接池属性
10.     private String driverName;
11.     private String url;
12.     private String userName;
13.     private String password;
14.     // 连接池名字
15.     private String poolName;
16.     private int minConnections = 1; // 空闲池,最小连接数
17.     private int maxConnections = 10; // 空闲池,最大连接数
18.
19.     private int initConnections = 5;// 初始化连接数
20.
21.     private long connTimeOut = 1000;// 重复获得连接的频率
22.
23.     private int maxActiveConnections = 100;// 最大允许的连接数,和数据库对应
24.
25.     private long connectionTimeOut = 1000*60*20;// 连接超时时间,默认20分钟
26.
27.     private boolean isCurrentConnection = true; // 是否获得当前连接,默认true
28.
29.     private boolean isCheakPool = true; // 是否定时检查连接池
30.     private long lazyCheck = 1000*60*60;// 延迟多少时间后开始 检查
31.     private long periodCheck = 1000*60*60;// 检查频率
32.
33.
34.
35.     public DBbean(String driverName, String url, String userName,
36.             String password, String poolName) {
37.         super();
38.         this.driverName = driverName;
39.         this.url = url;
40.         this.userName = userName;
41.         this.password = password;
42.         this.poolName = poolName;
43.     }
44.     public DBbean() {
45.     }
46.     public String getDriverName() {
47.         if(driverName == null){
48.             driverName = this.getDriverName()+"_"+this.getUrl();
49.         }
50.         return driverName;
51.     }
52.     public void setDriverName(String driverName) {
53.         this.driverName = driverName;
54.     }
55.     public String getUrl() {
56.         return url;
57.     }
58.     public void setUrl(String url) {
59.         this.url = url;
60.     }
61.     public String getUserName() {
62.         return userName;
63.     }
64.     public void setUserName(String userName) {
65.         this.userName = userName;
66.     }
67.     public String getPassword() {
68.         return password;
69.     }
70.     public void setPassword(String password) {
71.         this.password = password;
72.     }
73.     public String getPoolName() {
74.         return poolName;
75.     }
76.     public void setPoolName(String poolName) {
77.         this.poolName = poolName;
78.     }
79.     public int getMinConnections() {
80.         return minConnections;
81.     }
82.     public void setMinConnections(int minConnections) {
83.         this.minConnections = minConnections;
84.     }
85.     public int getMaxConnections() {
86.         return maxConnections;
87.     }
88.     public void setMaxConnections(int maxConnections) {
89.         this.maxConnections = maxConnections;
90.     }
91.     public int getInitConnections() {
92.         return initConnections;
93.     }
94.     public void setInitConnections(int initConnections) {
95.         this.initConnections = initConnections;
96.     }
97.
98.     public int getMaxActiveConnections() {
99.         return maxActiveConnections;
100.        }
101.        public void setMaxActiveConnections(int maxActiveConnections) {
102.            this.maxActiveConnections = maxActiveConnections;
103.        }
104.        public long getConnTimeOut() {
105.            return connTimeOut;
106.        }
107.        public void setConnTimeOut(long connTimeOut) {
108.            this.connTimeOut = connTimeOut;
109.        }
110.        public long getConnectionTimeOut() {
111.            return connectionTimeOut;
112.        }
113.        public void setConnectionTimeOut(long connectionTimeOut) {
114.            this.connectionTimeOut = connectionTimeOut;
115.        }
116.        public boolean isCurrentConnection() {
117.            return isCurrentConnection;
118.        }
119.        public void setCurrentConnection(boolean isCurrentConnection) {
120.            this.isCurrentConnection = isCurrentConnection;
121.        }
122.        public long getLazyCheck() {
123.            return lazyCheck;
124.        }
125.        public void setLazyCheck(long lazyCheck) {
126.            this.lazyCheck = lazyCheck;
127.        }
128.        public long getPeriodCheck() {
129.            return periodCheck;
130.        }
131.        public void setPeriodCheck(long periodCheck) {
132.            this.periodCheck = periodCheck;
133.        }
134.        public boolean isCheakPool() {
135.            return isCheakPool;
136.        }
137.        public void setCheakPool(boolean isCheakPool) {
138.            this.isCheakPool = isCheakPool;
139.        }
140.
141.
142.
143.    }

Java代码


1.  package pool;
2.
3.  import java.sql.Connection;
4.  import java.sql.SQLException;
5.
6.  public interface IConnectionPool {
7.      // 获得连接
8.      public Connection  getConnection();
9.      // 获得当前连接
10.     public Connection getCurrentConnecton();
11.     // 回收连接
12.     public void releaseConn(Connection conn) throws SQLException;
13.     // 销毁清空
14.     public void destroy();
15.     // 连接池是活动状态
16.     public boolean isActive();
17.     // 定时器,检查连接池
18.     public void cheackPool();
19. }  

Java代码


1.  package pool;
2.
3.  import java.sql.Connection;
4.  import java.sql.DriverManager;
5.  import java.sql.SQLException;
6.  import java.util.List;
7.  import java.util.Timer;
8.  import java.util.TimerTask;
9.  import java.util.Vector;
10.
11. public class ConnectionPool implements IConnectionPool {
12.     // 连接池配置属性
13.     private DBbean dbBean;
14.     private boolean isActive = false; // 连接池活动状态
15.     private int contActive = 0;// 记录创建的总的连接数
16.
17.     // 空闲连接
18.     private List<Connection> freeConnection = new Vector<Connection>();
19.     // 活动连接
20.     private List<Connection> activeConnection = new Vector<Connection>();
21.     // 将线程和连接绑定,保证事务能统一执行
22.     private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
23.
24.     public ConnectionPool(DBbean dbBean) {
25.         super();
26.         this.dbBean = dbBean;
27.         init();
28.         cheackPool();
29.     }
30.
31.     // 初始化
32.     public void init() {
33.         try {
34.             Class.forName(dbBean.getDriverName());
35.             for (int i = 0; i < dbBean.getInitConnections(); i++) {
36.                 Connection conn;
37.                 conn = newConnection();
38.                 // 初始化最小连接数
39.                 if (conn != null) {
40.                     freeConnection.add(conn);
41.                     contActive++;
42.                 }
43.             }
44.             isActive = true;
45.         } catch (ClassNotFoundException e) {
46.             e.printStackTrace();
47.         } catch (SQLException e) {
48.             e.printStackTrace();
49.         }
50.     }
51.
52.     // 获得当前连接
53.     public Connection getCurrentConnecton(){
54.         // 默认线程里面取
55.         Connection conn = threadLocal.get();
56.         if(!isValid(conn)){
57.             conn = getConnection();
58.         }
59.         return conn;
60.     }
61.
62.     // 获得连接
63.     public synchronized Connection getConnection() {
64.         Connection conn = null;
65.         try {
66.             // 判断是否超过最大连接数限制
67.             if(contActive < this.dbBean.getMaxActiveConnections()){
68.                 if (freeConnection.size() > 0) {
69.                     conn = freeConnection.get(0);
70.                     if (conn != null) {
71.                         threadLocal.set(conn);
72.                     }
73.                     freeConnection.remove(0);
74.                 } else {
75.                     conn = newConnection();
76.                 }
77.
78.             }else{
79.                 // 继续获得连接,直到从新获得连接
80.                 wait(this.dbBean.getConnTimeOut());
81.                 conn = getConnection();
82.             }
83.             if (isValid(conn)) {
84.                 activeConnection.add(conn);
85.                 contActive ++;
86.             }
87.         } catch (SQLException e) {
88.             e.printStackTrace();
89.         } catch (ClassNotFoundException e) {
90.             e.printStackTrace();
91.         } catch (InterruptedException e) {
92.             e.printStackTrace();
93.         }
94.         return conn;
95.     }
96.
97.     // 获得新连接
98.     private synchronized Connection newConnection()
99.             throws ClassNotFoundException, SQLException {
100.            Connection conn = null;
101.            if (dbBean != null) {
102.                Class.forName(dbBean.getDriverName());
103.                conn = DriverManager.getConnection(dbBean.getUrl(),
104.                        dbBean.getUserName(), dbBean.getPassword());
105.            }
106.            return conn;
107.        }
108.
109.        // 释放连接
110.        public synchronized void releaseConn(Connection conn) throws SQLException {
111.            if (isValid(conn)&& !(freeConnection.size() > dbBean.getMaxConnections())) {
112.                freeConnection.add(conn);
113.                activeConnection.remove(conn);
114.                contActive --;
115.                threadLocal.remove();
116.                // 唤醒所有正待等待的线程,去抢连接
117.                notifyAll();
118.            }
119.        }
120.
121.        // 判断连接是否可用
122.        private boolean isValid(Connection conn) {
123.            try {
124.                if (conn == null || conn.isClosed()) {
125.                    return false;
126.                }
127.            } catch (SQLException e) {
128.                e.printStackTrace();
129.            }
130.            return true;
131.        }
132.
133.        // 销毁连接池
134.        public synchronized void destroy() {
135.            for (Connection conn : freeConnection) {
136.                try {
137.                    if (isValid(conn)) {
138.                        conn.close();
139.                    }
140.                } catch (SQLException e) {
141.                    e.printStackTrace();
142.                }
143.            }
144.            for (Connection conn : activeConnection) {
145.                try {
146.                    if (isValid(conn)) {
147.                        conn.close();
148.                    }
149.                } catch (SQLException e) {
150.                    e.printStackTrace();
151.                }
152.            }
153.            isActive = false;
154.            contActive = 0;
155.        }
156.
157.        // 连接池状态
158.        @Override
159.        public boolean isActive() {
160.            return isActive;
161.        }
162.
163.        // 定时检查连接池情况
164.        @Override
165.        public void cheackPool() {
166.            if(dbBean.isCheakPool()){
167.                new Timer().schedule(new TimerTask() {
168.                @Override
169.                public void run() {
170.                // 1.对线程里面的连接状态
171.                // 2.连接池最小 最大连接数
172.                // 3.其他状态进行检查,因为这里还需要写几个线程管理的类,暂时就不添加了
173.                System.out.println("空线池连接数:"+freeConnection.size());
174.                System.out.println("活动连接数::"+activeConnection.size());
175.                System.out.println("总的连接数:"+contActive);
176.                    }
177.                },dbBean.getLazyCheck(),dbBean.getPeriodCheck());
178.            }
179.        }
180.    }  

Java代码
1. package pool;
2.
3. import java.sql.Connection;
4. import java.sql.SQLException;
5. import java.util.Hashtable;
6. /**
7. * 连接管理类
8. * @author Ran
9. *
10. */
11. public class ConnectionPoolManager {
12.
13.
14. // 连接池存放
15. public Hashtable


1.  package pool;
2.
3.  import java.sql.Connection;
4.  /**
5.   * 模拟线程启动,去获得连接
6.   * @author Ran
7.   *
8.   */
9.  public class ThreadConnection implements Runnable{
10.     private IConnectionPool pool;
11.     @Override
12.     public void run() {
13.         pool = ConnectionPoolManager.getInstance().getPool("testPool");
14.     }
15.
16.     public Connection getConnection(){
17.         Connection conn = null;
18.         if(pool != null && pool.isActive()){
19.             conn = pool.getConnection();
20.         }
21.         return conn;
22.     }
23.
24.     public Connection getCurrentConnection(){
25.         Connection conn = null;
26.         if(pool != null && pool.isActive()){
27.             conn = pool.getCurrentConnecton();
28.         }
29.         return conn;
30.     }
31. }  

Java代码


1.  package pool;
5.  public class Client {
6.      public static void main(String[] args) throws InterruptedException {
7.          // 初始化连接池
8.          Thread t = init();
9.          t.start();
10.         t.join();
11.
12.         ThreadConnection a = new ThreadConnection();
13.         ThreadConnection b = new ThreadConnection();
14.         ThreadConnection c = new ThreadConnection();
15.         Thread t1 = new Thread(a);
16.         Thread t2 = new Thread(b);
17.         Thread t3 = new Thread(c);
18.
19.
20.         // 设置优先级,先让初始化执行,模拟 线程池 先启动
21.         // 这里仅仅表面控制了,因为即使t 线程先启动,也不能保证pool 初始化完成,为了简单模拟,这里先这样写了
22.         t1.setPriority(10);
23.         t2.setPriority(10);
24.         t3.setPriority(10);
25.         t1.start();
26.         t2.start();
27.         t3.start();
28.
29.         System.out.println("线程A-> "+a.getConnection());
30.         System.out.println("线程B-> "+b.getConnection());
31.         System.out.println("线程C-> "+c.getConnection());
32.     }
33.
34.     // 初始化
35.     public static Thread init() {
36.         Thread t = new Thread(new Runnable() {
37.             @Override
38.             public void run() {
39.                 IConnectionPool  pool = initPool();
40.                 while(pool == null || !pool.isActive()){
41.                     pool = initPool();
42.                 }
43.             }
44.         });
45.         return t;
46.     }
47.
48.     public static IConnectionPool initPool(){
49.         return ConnectionPoolManager.getInstance().getPool("testPool");
50.     }
51.
52. }  

小结 :
1.连接池诞生原因是,如果每次都从数据库获得连接,时间比较长,因此我们提前做建立一些连接,放在连接池里面,每次都从里面取
2.上面仅仅写了连接池基本原理,关于多线程下连接池的管理没写,后面对多线程操作熟练了添加吧

多线程情况下创建连接池相关推荐

  1. 线程池是什么?什么情况下使用线程池?使用线程的好处是什么?

    线程池:是一种多线程处理形式,处理线程时将任务添加到队列里,等创建好线程再执行队列里任务.线程池的线程都是后台线程.每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中. 什么情况下使 ...

  2. 在不重装系统的情况下创建Linux的Swap分区

    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/wy_bk/article/detail ...

  3. 无屏幕有线情况下笔记本电脑连接树莓派

    无屏幕有线情况下笔记本电脑连接树莓派 获取树莓派ip 使用SSH远程登录树莓派 远程VNC桌面服务访问 首先我们需要将网线接入到树莓派中,如下: 获取树莓派ip 1. 假如有屏幕的话可以通过在树莓派L ...

  4. python设计一个节假日字典_python实现在无须过多援引的情况下创建字典的方法

    本文实例讲述了python实现在无须过多援引的情况下创建字典的方法.分享给大家供大家参考.具体实现方法如下: 1.使用itertools模块 import itertools the_key = [' ...

  5. Spring Cloud Feign传输Header,并保证多线程情况下也适用

    Spring Cloud Feign传输Header,并保证多线程情况下也适用 一.现象 微服务在生产中,常遇到需要把 header 传递到下一子服务的情况(如服务A访问服务B的接口,需要传递head ...

  6. Spring Boot下Druid连接池的使用配置分析

    引言: 在Spring Boot下默认提供了若干种可用的连接池,Druid来自于阿里系的一个开源连接池,在连接池之外,还提供了非常优秀的监控功能,这里讲解如何与Spring Boot实现集成. 1.  ...

  7. oracle数据库什么情况下创建索引比较好

    索引就好象一本字典的目录.凭借字典的目录,我们可以非常迅速的找到我们所需要的条目.数据库也是如此.凭借Oracle数据库的索引,相关语句可以迅速的定位记录的位置,而不必去定位整个表. 虽 然说,在表中 ...

  8. python调用libs.dbutil_Python 使用 PyMysql、DBUtils 创建连接池,提升性能

    Python 编程中可以使用 PyMysql 进行数据库的连接及诸如查询/插入/更新等操作,但是每次连接 MySQL 数据库请求时,都是独立的去请求访问,相当浪费资源,而且访问数量达到一定数量时,对 ...

  9. nodejs mysql 创建连接池

    用Nodejs连接MySQL 从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发.Nodejs框架是基于V8的引擎,是目前速度最快的Javas ...

最新文章

  1. FPGA实验——译码器原理及实现
  2. 利用计算机进行自动控制 控制对象主要指,计算机试卷10
  3. php imagemagick 漏洞,ImageMagick漏洞(CVE-2016-3714)修复方案
  4. 每日英语:Go Ahead, Hit the Snooze Button
  5. 阿里CTO:阿里所有技术和产品输出都将必须通过阿里云进行
  6. Pentium 4处理器架构/微架构/流水线 (6) - NetBurst前端详解 - 取指/译码/缓存
  7. mongodb java and or,【MongoDB】-Java实现对mongodb的And、Or、In操作
  8. 2021年广东新高考学业水平考试成绩查询,2021年1月广东高中学业水平考试成绩查询时间及入口...
  9. 利用 TFLearn 快速搭建经典深度学习模型
  10. 测试压缩ASP.NET中的ViewState
  11. attachEvent方法绑定事件
  12. Parasoft c++test安装使用导引
  13. 001-取整函数(ceil、floor、round)
  14. (译)使用Go语言从零编写PoS区块链
  15. Unity与讯飞语音交互:使用aiui技能
  16. 全新版大学英语综合教程第一册学习笔记(原文及全文翻译)——5 - A Valentine Story(爱情故事)
  17. 一份超详细的网站推广优化方案 1
  18. 开发以及团队管理方面的心得总结
  19. HTML详解——初识html(一)
  20. DrugBank数据库以及其他介绍

热门文章

  1. 关于sendinput() inserted only 0 out of 2 python程序问题的解决
  2. [architecture]-Armv8 Cryptographic Extension介绍
  3. 数据结构考完,想了很多。
  4. linux script 命令
  5. VMProtect SDK+ASProtect SDK保护
  6. *ctf box题解
  7. 系统调用004 SSDT
  8. 系统调用002 KiSystemService函数逆向分析
  9. 4、MySQL使用二进制日志还原数据库
  10. 1.2 内置异常类,异常方法