• 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<String,IConnectionPool> pools = new Hashtable<String, IConnectionPool>();  
    16.       
    17.     // 初始化  
    18.     private ConnectionPoolManager(){  
    19.         init();  
    20.     }  
    21.     // 单例实现  
    22.     public static ConnectionPoolManager getInstance(){  
    23.         return Singtonle.instance;  
    24.     }  
    25.     private static class Singtonle {  
    26.         private static ConnectionPoolManager instance =  new ConnectionPoolManager();  
    27.     }  
    28.       
    29.       
    30.     // 初始化所有的连接池  
    31.     public void init(){  
    32.         for(int i =0;i<DBInitInfo.beans.size();i++){  
    33.             DBbean bean = DBInitInfo.beans.get(i);  
    34.             ConnectionPool pool = new ConnectionPool(bean);  
    35.             if(pool != null){  
    36.                 pools.put(bean.getPoolName(), pool);  
    37.                 System.out.println("Info:Init connection successed ->" +bean.getPoolName());  
    38.             }  
    39.         }  
    40.     }  
    41.       
    42.     // 获得连接,根据连接池名字 获得连接  
    43.     public Connection  getConnection(String poolName){  
    44.         Connection conn = null;  
    45.         if(pools.size()>0 && pools.containsKey(poolName)){  
    46.             conn = getPool(poolName).getConnection();  
    47.         }else{  
    48.             System.out.println("Error:Can't find this connecion pool ->"+poolName);  
    49.         }  
    50.         return conn;  
    51.     }  
    52.       
    53.     // 关闭,回收连接  
    54.     public void close(String poolName,Connection conn){  
    55.             IConnectionPool pool = getPool(poolName);  
    56.             try {  
    57.                 if(pool != null){  
    58.                     pool.releaseConn(conn);  
    59.                 }  
    60.             } catch (SQLException e) {  
    61.                 System.out.println("连接池已经销毁");  
    62.                 e.printStackTrace();  
    63.             }  
    64.     }  
    65.       
    66.     // 清空连接池  
    67.     public void destroy(String poolName){  
    68.         IConnectionPool pool = getPool(poolName);  
    69.         if(pool != null){  
    70.             pool.destroy();  
    71.         }  
    72.     }  
    73.       
    74.     // 获得连接池  
    75.     public IConnectionPool getPool(String poolName){  
    76.         IConnectionPool pool = null;  
    77.         if(pools.size() > 0){  
    78.              pool = pools.get(poolName);  
    79.         }  
    80.         return pool;  
    81.     }  
    82. }  
    Java代码  收藏代码
    1. package pool;  
    2.   
    3. import java.util.ArrayList;  
    4. import java.util.List;  
    5. /** 
    6.  * 初始化,模拟加载所有的配置文件 
    7.  * @author Ran 
    8.  * 
    9.  */  
    10. public class DBInitInfo {  
    11.     public  static List<DBbean>  beans = null;  
    12.     static{  
    13.         beans = new ArrayList<DBbean>();  
    14.         // 这里数据 可以从xml 等配置文件进行获取  
    15.         // 为了测试,这里我直接写死  
    16.         DBbean beanOracle = new DBbean();  
    17.         beanOracle.setDriverName("oracle.jdbc.driver.OracleDriver");  
    18.         beanOracle.setUrl("jdbc:oracle:thin:@7MEXGLUY95W1Y56:1521:orcl");  
    19.         beanOracle.setUserName("mmsoa");  
    20.         beanOracle.setPassword("password1234");  
    21.           
    22.         beanOracle.setMinConnections(5);  
    23.         beanOracle.setMaxConnections(100);  
    24.           
    25.         beanOracle.setPoolName("testPool");  
    26.         beans.add(beanOracle);  
    27.     }  
    28. }  

        测试:

       

    Java代码  收藏代码
    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;  
    2.   
    3.   
    4.   
    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.上面仅仅写了连接池基本原理,关于多线程下连接池的管理没写,后面对多线程操作熟练了添加吧

    本文转自http://greemranqq.iteye.com/blog/1969273 感谢作者

  • 相关阅读:
    C#学习三之几个关键字Static,ref&out,get&set,readonly
    C#学习二之浅析var类型和enum枚举类型
    C#学习一之HelloWorld
    泛型(二)
    泛型(一)
    JavaScript 使用
    JavaScript
    C# 自定义控件制作和使用实例(winform)
    ThinkPHP 参数绑定原理
    处理jQuery append加入的元素 绑定事件无效的方法
  • 原文地址:https://www.cnblogs.com/panxuejun/p/5970855.html
Copyright © 2020-2023  润新知