博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
简易连接池
阅读量:5931 次
发布时间:2019-06-19

本文共 12742 字,大约阅读时间需要 42 分钟。

hot3.png

[代码] 连接池类

001 package com.sli.util;
002  
003 import java.io.FileInputStream;
004 import java.sql.Connection;
005 import java.sql.DriverManager;
006 import java.sql.SQLException;
007 import java.util.Enumeration;
008 import java.util.HashMap;
009 import java.util.LinkedList;
010 import java.util.Map;
011 import java.util.Properties;
012 import java.util.Timer;
013 import java.util.TimerTask;
014  
015 public class DataSourcePool {
016  
017     static int connectionCurrLink = 0;
018     static Map<String, String> map = null;
019     private static LinkedList<Connection> datasourcePool = newLinkedList<Connection>();
020     // 通过静态代码块注册数据库驱动,保证注册只执行一次
021     static {
022         map = new HashMap<String, String>();
023         Properties p = new Properties();
024         try {
025             p.loadFromXML(newFileInputStream("src\\DataSourcePool.xml"));
026             Enumeration<Object> dataSourceSet = p.keys();
027             while (dataSourceSet.hasMoreElements()) {
028                 String key = (String) dataSourceSet.nextElement();
029                 map.put(key, p.getProperty(key));
030             }
031             Class.forName(map.get("conectionDriver"));
032         } catch (Exception e) {
033             e.printStackTrace();
034         }
035     }
036  
037     public DataSourcePool() throws Exception {
038         createConnection(0);
039         // 通过构造函数启动定时器以达到定时释放空闲连接目的
040         Timer timer = new Timer();
041         timer.schedule(new TimerTask() {
042             @Override
043             public void run() {
044                 try {
045                     // 得到空闲连接,datasourcePool里面有几个对象就表示有几个空闲连接
046                     int leisureLink = DataSourcePool.datasourcePool.size();
047                     System.out.println(leisureLink);
048                     // 最小连接数
049                     int connectionMinLink = Integer.parseInt(DataSourcePool.map
050                             .get("connectionMinLink"));
051                     // 当空闲连接大于DataSourcePool设置的最小连接数时则关闭
052                     if (leisureLink > connectionMinLink) {
053                         for (int i = 0; i < leisureLink - connectionMinLink; i++) {
054                             DataSourcePool.closeConnection(DataSourcePool.getConnection());
055                             connectionCurrLink--;
056                         }
057                     } else {
058                         System.out.println("保持最小连接,将继续保持连接池");
059                     }
060                 } catch (NumberFormatException e) {
061                     throw new NumberFormatException("设置了无效的最小连接数");
062                 } catch (SQLException e) {
063                     e.printStackTrace();
064                 } catch (Exception e) {
065                     e.printStackTrace();
066                 }
067             }
068         }, 0, Long.parseLong(map.get("connectionTimer")));
069  
070     }
071  
072     // 创建连接
073     private static void createConnection(int type) throws Exception {
074         try {
075             int link = 0;
076             switch (type) {
077             case 0:
078                 link = Integer.parseInt(map.get("connectionMinLink"));
079                 break;
080             case 1:
081                 //如果当前连接+增长连接大于设定的最大连接数时,将使用最大连接数-当前连接的数量。以保持平衡
082                 link = Integer.parseInt(map.get("connectionIncreaseLink"));
083                 int maxLink = Integer.parseInt(map.get("conectionMaxLink"));
084                 if (link + connectionCurrLink > maxLink) {
085                     link = maxLink - connectionCurrLink;
086                 }
087                 break;
088             }
089             for (int i = 0; i < link; i++) {
090                 datasourcePool.addLast(DriverManager.getConnection(map.get("connectionUrl"),
091                         map.get("connectionName"), map.get("connectionPassword")));
092                 connectionCurrLink++;
093             }
094         } catch (NumberFormatException n) {
095             throw new NumberFormatException("配置连接参数有误");
096         } catch (Exception e) {
097             e.printStackTrace();
098             throw new SQLException("超过最大连接数 ,无法创建更多连接");
099         }
100     }
101  
102     // 获得连接
103     public static Connection getConnection() throws Exception {
104         // 取连接加锁,防止并发取的同样的连接
105         synchronized (datasourcePool) {
106             if (datasourcePool.size() > 0) {
107                 return datasourcePool.removeFirst();
108             } else if (connectionCurrLink < Integer.parseInt(map.get("conectionMaxLink"))) {
109                 createConnection(1);
110                 return datasourcePool.removeFirst();
111             }
112         }
113         return null;
114     }
115  
116     /**
117      * 关闭连接
118      *
119      * @param con
120      * SQLException
121      */
122     public static void closeConnection(Connection con) throwsSQLException {
123         con.close();
124     }
125  
126     // 释放连接
127     public void freeConnection(Connection con) {
128         datasourcePool.addLast(con);
129     }
130  
131 }

[代码] jdbcUtil作为封装连接池的辅助类

01 package com.sli.util;
02  
03 import java.sql.Connection;
04 import java.sql.ResultSet;
05 import java.sql.SQLException;
06 import java.sql.Statement;
07  
08 /**
09  *
10  * 罗盛力 模拟连接池(封装连接池)
11  */
12 public final class JDBCUtil {
13     private static DataSourcePool dsp = null;
14  
15     public JDBCUtil() throws Exception {
16          
17     }
18  
19     /**
20      * 获得连接
21      *
22      * Exception
23      */
24     public static Connection getConnection( ) throws Exception {
25         if (dsp == null) {
26             synchronized (DataSourcePool.class) {
27                 if (dsp == null) {
28                     dsp = new DataSourcePool();
29                 }
30             }
31         }
32         return dsp.getConnection();
33     }
34  
35     // 关闭连接
36     public static void freeConnection(ResultSet rs, Statement ps, Connection con)
37             throws SQLException {
38         try {
39             if (rs != null) {
40                 rs.close();
41             }
42         } catch (SQLException e) {
43             e.printStackTrace();
44         } finally {
45             try {
46                 if (ps != null) {
47                     ps.close();
48                 }
49             } catch (Exception e) {
50                 e.printStackTrace();
51             } finally {
52                 if (con != null) {
53                     dsp.freeConnection(con);
54                 }
55             }
56         }
57     }
58     // 关闭连接
59         public static void freeConnection(Connection con)
60                 throws SQLException {
61                     if (con != null) {
62                         dsp.freeConnection(con);
63                     }
64         }
65       
66 }

[代码] 测试类

01 package com.sli.test;
02  
03 import java.sql.Connection;
04  
05 import com.sli.util.JDBCUtil;
06  
07 public class TestDataPool {
08     public static void main(String[] args) throws Exception {
09         long start = System.currentTimeMillis();
10         int j=0;
11         System.out.println("连接池开始:" + start);
12         for (int i = 0; i <20; i++) {
13             Connection con = JDBCUtil.getConnection();
14             System.out.println(con);
15             if(i<14) {
16                 JDBCUtil.freeConnection(con);
17             }
18         }
19         long end = System.currentTimeMillis();
20         System.out.println("连接池结束:" + end);
21         System.out.println("连接池耗时:" + (end - start));
22     }
23 }

[代码] 配置连接xml

01 <?xml version="1.0" encoding="utf-8"?>
02 <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> 
03 <properties>
04    <!-- 连接url -->
05    <entry key="connectionUrl">jdbc:mysql:///test</entry> 
06    <!-- 用户名 -->
07    <entry key="connectionName">root</entry> 
08    <!-- 密码 -->
09    <entry key="connectionPassword">sli</entry> 
10    <!-- 最小连接数(首次以此值为创建连接数标准及空闲连接大于该数时则会清除) -->
11    <entry key="connectionMinLink">5</entry>
12    <!-- 最大连接数 -->
13    <entry key="conectionMaxLink">89</entry>
14     <!-- 驱动 -->
15    <entry key="conectionDriver">com.mysql.jdbc.Driver</entry>
16    <!--  当连接不够用时的增长率-->
17    <entry key="connectionIncreaseLink">10</entry>
18    <!--  设定自动清除空闲连接时间(毫秒)-->
19    <entry key="connectionTimer">5000</entry>
20 </properties>

代码片段(4)

[代码] 连接池类

001 package com.sli.util;
002  
003 import java.io.FileInputStream;
004 import java.sql.Connection;
005 import java.sql.DriverManager;
006 import java.sql.SQLException;
007 import java.util.Enumeration;
008 import java.util.HashMap;
009 import java.util.LinkedList;
010 import java.util.Map;
011 import java.util.Properties;
012 import java.util.Timer;
013 import java.util.TimerTask;
014  
015 public class DataSourcePool {
016  
017     static int connectionCurrLink = 0;
018     static Map<String, String> map = null;
019     private static LinkedList<Connection> datasourcePool = newLinkedList<Connection>();
020     // 通过静态代码块注册数据库驱动,保证注册只执行一次
021     static {
022         map = new HashMap<String, String>();
023         Properties p = new Properties();
024         try {
025             p.loadFromXML(newFileInputStream("src\\DataSourcePool.xml"));
026             Enumeration<Object> dataSourceSet = p.keys();
027             while (dataSourceSet.hasMoreElements()) {
028                 String key = (String) dataSourceSet.nextElement();
029                 map.put(key, p.getProperty(key));
030             }
031             Class.forName(map.get("conectionDriver"));
032         } catch (Exception e) {
033             e.printStackTrace();
034         }
035     }
036  
037     public DataSourcePool() throws Exception {
038         createConnection(0);
039         // 通过构造函数启动定时器以达到定时释放空闲连接目的
040         Timer timer = new Timer();
041         timer.schedule(new TimerTask() {
042             @Override
043             public void run() {
044                 try {
045                     // 得到空闲连接,datasourcePool里面有几个对象就表示有几个空闲连接
046                     int leisureLink = DataSourcePool.datasourcePool.size();
047                     System.out.println(leisureLink);
048                     // 最小连接数
049                     int connectionMinLink = Integer.parseInt(DataSourcePool.map
050                             .get("connectionMinLink"));
051                     // 当空闲连接大于DataSourcePool设置的最小连接数时则关闭
052                     if (leisureLink > connectionMinLink) {
053                         for (int i = 0; i < leisureLink - connectionMinLink; i++) {
054                             DataSourcePool.closeConnection(DataSourcePool.getConnection());
055                             connectionCurrLink--;
056                         }
057                     } else {
058                         System.out.println("保持最小连接,将继续保持连接池");
059                     }
060                 } catch (NumberFormatException e) {
061                     throw new NumberFormatException("设置了无效的最小连接数");
062                 } catch (SQLException e) {
063                     e.printStackTrace();
064                 } catch (Exception e) {
065                     e.printStackTrace();
066                 }
067             }
068         }, 0, Long.parseLong(map.get("connectionTimer")));
069  
070     }
071  
072     // 创建连接
073     private static void createConnection(int type) throws Exception {
074         try {
075             int link = 0;
076             switch (type) {
077             case 0:
078                 link = Integer.parseInt(map.get("connectionMinLink"));
079                 break;
080             case 1:
081                 //如果当前连接+增长连接大于设定的最大连接数时,将使用最大连接数-当前连接的数量。以保持平衡
082                 link = Integer.parseInt(map.get("connectionIncreaseLink"));
083                 int maxLink = Integer.parseInt(map.get("conectionMaxLink"));
084                 if (link + connectionCurrLink > maxLink) {
085                     link = maxLink - connectionCurrLink;
086                 }
087                 break;
088             }
089             for (int i = 0; i < link; i++) {
090                 datasourcePool.addLast(DriverManager.getConnection(map.get("connectionUrl"),
091                         map.get("connectionName"), map.get("connectionPassword")));
092                 connectionCurrLink++;
093             }
094         } catch (NumberFormatException n) {
095             throw new NumberFormatException("配置连接参数有误");
096         } catch (Exception e) {
097             e.printStackTrace();
098             throw new SQLException("超过最大连接数 ,无法创建更多连接");
099         }
100     }
101  
102     // 获得连接
103     public static Connection getConnection() throws Exception {
104         // 取连接加锁,防止并发取的同样的连接
105         synchronized (datasourcePool) {
106             if (datasourcePool.size() > 0) {
107                 return datasourcePool.removeFirst();
108             } else if (connectionCurrLink < Integer.parseInt(map.get("conectionMaxLink"))) {
109                 createConnection(1);
110                 return datasourcePool.removeFirst();
111             }
112         }
113         return null;
114     }
115  
116     /**
117      * 关闭连接
118      *
119      * @param con
120      * SQLException
121      */
122     public static void closeConnection(Connection con) throwsSQLException {
123         con.close();
124     }
125  
126     // 释放连接
127     public void freeConnection(Connection con) {
128         datasourcePool.addLast(con);
129     }
130  
131 }

[代码] jdbcUtil作为封装连接池的辅助类

01 package com.sli.util;
02  
03 import java.sql.Connection;
04 import java.sql.ResultSet;
05 import java.sql.SQLException;
06 import java.sql.Statement;
07  
08 /**
09  *
10  * 罗盛力 模拟连接池(封装连接池)
11  */
12 public final class JDBCUtil {
13     private static DataSourcePool dsp = null;
14  
15     public JDBCUtil() throws Exception {
16          
17     }
18  
19     /**
20      * 获得连接
21      *
22      * Exception
23      */
24     public static Connection getConnection( ) throws Exception {
25         if (dsp == null) {
26             synchronized (DataSourcePool.class) {
27                 if (dsp == null) {
28                     dsp = new DataSourcePool();
29                 }
30             }
31         }
32         return dsp.getConnection();
33     }
34  
35     // 关闭连接
36     public static void freeConnection(ResultSet rs, Statement ps, Connection con)
37             throws SQLException {
38         try {
39             if (rs != null) {
40                 rs.close();
41             }
42         } catch (SQLException e) {
43             e.printStackTrace();
44         } finally {
45             try {
46                 if (ps != null) {
47                     ps.close();
48                 }
49             } catch (Exception e) {
50                 e.printStackTrace();
51             } finally {
52                 if (con != null) {
53                     dsp.freeConnection(con);
54                 }
55             }
56         }
57     }
58     // 关闭连接
59         public static void freeConnection(Connection con)
60                 throws SQLException {
61                     if (con != null) {
62                         dsp.freeConnection(con);
63                     }
64         }
65       
66 }

[代码] 测试类

01 package com.sli.test;
02  
03 import java.sql.Connection;
04  
05 import com.sli.util.JDBCUtil;
06  
07 public class TestDataPool {
08     public static void main(String[] args) throws Exception {
09         long start = System.currentTimeMillis();
10         int j=0;
11         System.out.println("连接池开始:" + start);
12         for (int i = 0; i <20; i++) {
13             Connection con = JDBCUtil.getConnection();
14             System.out.println(con);
15             if(i<14) {
16                 JDBCUtil.freeConnection(con);
17             }
18         }
19         long end = System.currentTimeMillis();
20         System.out.println("连接池结束:" + end);
21         System.out.println("连接池耗时:" + (end - start));
22     }
23 }

[代码] 配置连接xml

01 <?xml version="1.0" encoding="utf-8"?>
02 <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> 
03 <properties>
04    <!-- 连接url -->
05    <entry key="connectionUrl">jdbc:mysql:///test</entry> 
06    <!-- 用户名 -->
07    <entry key="connectionName">root</entry> 
08    <!-- 密码 -->
09    <entry key="connectionPassword">sli</entry> 
10    <!-- 最小连接数(首次以此值为创建连接数标准及空闲连接大于该数时则会清除) -->
11    <entry key="connectionMinLink">5</entry>
12    <!-- 最大连接数 -->
13    <entry key="conectionMaxLink">89</entry>
14     <!-- 驱动 -->
15    <entry key="conectionDriver">com.mysql.jdbc.Driver</entry>
16    <!--  当连接不够用时的增长率-->
17    <entry key="connectionIncreaseLink">10</entry>
18    <!--  设定自动清除空闲连接时间(毫秒)-->
19    <entry key="connectionTimer">5000</entry>
20 </properties>

转载于:https://my.oschina.net/lvzjane/blog/103810

你可能感兴趣的文章
投简历申请数据科学岗石沉大海?这些秘密别人不会告诉你
查看>>
BitBucket引入灾难恢复和合并策略
查看>>
Node.js 2017企业用户调查结果发布
查看>>
InfoQ中文站2015年度优秀社区编辑评选揭晓
查看>>
GitHub贡献第一的公司是谁?微软开源软件列表
查看>>
中国在两年内赶超美国AI?李开复:不一定
查看>>
埃森哲、亚马逊和万事达卡抱团推出的区块链项目有何神通?
查看>>
Node 7.6默认支持Async/Await
查看>>
.NET Core如何为项目提供高性能解决方案?
查看>>
你以为AlphaGo只是下围棋厉害?不,它还能用来优化金融交易策略参数
查看>>
HashMap源码分析
查看>>
compass watch 报CompatibilityError 解决方案
查看>>
Payara基金会发布全面支持MicroProfile 2.0的5.183版Payara Server和Payara Micro
查看>>
函数式编程语言时代已经来临
查看>>
Yarn将用TypeScript重写,Flow惨遭亲爹抛弃!
查看>>
Visual Studio 2017 15.7预览版发布
查看>>
Python数据科学平台Anaconda的最新发布中增加了Microsoft VS Code
查看>>
利用媒体云实现差异化
查看>>
Imperva开源域目录控制器,简化活动目录集成
查看>>
保Cloudera弃Hortonworks,新平台将支持五大云供应商
查看>>