[Java] Java实现简单的数据库连接池代码 →→→→→进入此内容的聊天室

来自 , 2021-01-15, 写在 Java, 查看 128 次.
URL http://www.code666.cn/view/cba0a4ee
  1. package org.apple.connectionpool;
  2.  
  3. import java.io.IOException;
  4. import java.sql.Connection;
  5. import java.sql.DriverManager;
  6. import java.sql.SQLException;
  7. import java.util.Collections;
  8. import java.util.Date;
  9. import java.util.Enumeration;
  10. import java.util.HashMap;
  11. import java.util.Iterator;
  12. import java.util.Map;
  13. import java.util.Properties;
  14. import java.util.Set;
  15. import java.util.Timer;
  16. import java.util.TimerTask;
  17. import java.util.Vector;
  18. import java.util.logging.Logger;
  19.  
  20. public class DbConnectionManager {
  21.  
  22.         private static DbConnectionManager dbConnectionManager = new DbConnectionManager();
  23.         private static Properties properties = new Properties();
  24.         private static DbConnectionPool pool = null;
  25.         static {
  26.                 try {
  27.                         properties.load(DbConnectionManager.class.getResourceAsStream("/org/apple/connectionpool/connectionpoll.properties"));
  28.                         pool = new DbConnectionPool(properties.getProperty("driverClass").trim(), properties.getProperty("url").trim(), properties.getProperty("username").trim(), properties.getProperty("password").trim(), Integer.parseInt(properties.getProperty("minConns").trim()), Integer.parseInt(properties.getProperty("maxConns").trim()));
  29.                 } catch (IOException e) {
  30.                         e.printStackTrace();
  31.                 }
  32.         }
  33.  
  34.         public static DbConnectionManager getInstance() {
  35.                 if (dbConnectionManager != null) {
  36.                         return dbConnectionManager;
  37.                 } else {
  38.                         return new DbConnectionManager();
  39.                 }
  40.         }
  41.  
  42.         public static void main(String[] args) throws SQLException {
  43.                 for (int i = 0; i < 23; i++) {
  44.                         Connection connection = DbConnectionManager.getInstance().getConnection();
  45.                         System.out.println(connection);
  46.                         DbConnectionManager.getInstance().close(connection);
  47.                 }
  48.                 for (int i = 0; i < 10; i++) {
  49.                         Connection connection = DbConnectionManager.getInstance().getConnection();
  50.                         System.out.println(connection);
  51.                         DbConnectionManager.getInstance().close(connection);
  52.                 }
  53.  
  54.         }
  55.  
  56.         private DbConnectionManager() {
  57.         }
  58.  
  59.         public void close(Connection conn) throws SQLException {
  60.                 if (conn != null) {
  61.                         pool.freeConnection(conn);
  62.                 }
  63.  
  64.         }
  65.  
  66.         // ----------对外提供的方法----------
  67.  
  68.         // ----------对外提供的方法----------
  69.         public Connection getConnection() {
  70.                 return pool.getConnection();
  71.         }
  72.  
  73.         public void releaseAll() {
  74.                 pool.releaseAll();
  75.         }
  76.  
  77. }
  78.  
  79. class DbConnectionPool {
  80.  
  81.         private final static Logger logger = Logger.getLogger(DbConnectionPool.class.getName());
  82.         private static Vector<Connection> freeConnections = new Vector<Connection>();
  83.         private static Map<String, ConnectionAndStartTime> busyConnectionsMap = Collections.synchronizedMap(new HashMap<String, ConnectionAndStartTime>());
  84.         /**
  85.          * 计时统计
  86.          */
  87.         private static Timer timer = new Timer();
  88.         private static long timerCount = 0;
  89.         private static int timeOut = 30;
  90.         static {
  91.                 // 另起一个线程
  92.                 new Thread(new Runnable() {
  93.                         public void run() {
  94.                                 timer.schedule(new TimerTask() {
  95.  
  96.                                         @Override
  97.                                         public void run() {
  98.                                                 if (LogUtil.isDebug()) {
  99.                                                         logger.info("----------[清除超时的线程进行清除...----------");
  100.                                                 }
  101.                                                 if (LogUtil.isInfo()) {
  102.                                                         System.out.println("----------[清除超时的线程进行清除...----------");
  103.                                                 }
  104.  
  105.                                                 timerCount++;
  106.                                                 if (timerCount >= 100000000) {
  107.                                                         timerCount = 0;
  108.                                                 }
  109.                                                 if (LogUtil.isDebug()) {
  110.                                                         System.out.println("第" + timerCount + "进行定时清除超时的数据库连接");
  111.                                                 }
  112.                                                 if (LogUtil.isDebug()) {
  113.                                                         System.out.println("----------[清除超时的线程进行清除...----------");
  114.                                                 }
  115.                                                 Set<String> set = busyConnectionsMap.keySet();
  116.                                                 Iterator<String> iterator = set.iterator();
  117.                                                 String connectionAndTimeKeyArray = "";
  118.                                                 int index = 0;
  119.                                                 while (iterator.hasNext()) {
  120.                                                         String connectionClassString = iterator.next();
  121.                                                         ConnectionAndStartTime connectionAndTime = busyConnectionsMap.get(connectionClassString);
  122.                                                         if (new Date().getTime() - connectionAndTime.getStartTime() > timeOut * 1000) {// 大于2分钟
  123.                                                                 if (index == 0) {
  124.                                                                         connectionAndTimeKeyArray += connectionClassString;
  125.                                                                 } else {
  126.                                                                         connectionAndTimeKeyArray += "," + connectionClassString;
  127.                                                                 }
  128.                                                                 index++;
  129.                                                         }
  130.  
  131.                                                 }
  132.                                                 // 清除
  133.                                                 if (connectionAndTimeKeyArray != null && connectionAndTimeKeyArray != "") {
  134.                                                         String[] connectionClassStringArray = connectionAndTimeKeyArray.split(",");
  135.                                                         for (int i = 0; i < connectionClassStringArray.length; i++) {
  136.                                                                 if (busyConnectionsMap.get(connectionClassStringArray[i]) != null) {
  137.                                                                         System.out.println("connectionClassStringArray[i]" + connectionClassStringArray[i]);
  138.                                                                         busyConnectionsMap.remove(connectionClassStringArray[i]);
  139.                                                                         if (LogUtil.isDebug()) {
  140.                                                                                 System.out.println("清除超时的Connection:" + connectionClassStringArray[i]);
  141.                                                                         }
  142.                                                                         isUsed--;
  143.                                                                 }
  144.  
  145.                                                         }
  146.                                                 }
  147.                                                 if (LogUtil.isDebug()) {
  148.                                                         System.out.println("当前数据库可用连接" + freeConnections.size());
  149.                                                         System.out.println("----------[清除超时的线程进行清除...----------");
  150.                                                         System.out.println("----------[清除超时的线程成功]----------");
  151.                                                 }
  152.  
  153.                                         }
  154.                                         // 30秒后执行定时操作:每个10秒检查是否超时
  155.                                 }, 30 * 1000, 10 * 1000);
  156.  
  157.                         }
  158.                 }).start();
  159.                 if (LogUtil.isInfo()) {
  160.                         System.out.println("超时处理Connection线程启动");
  161.                 }
  162.                 if (LogUtil.isInfo()) {
  163.  
  164.                 }
  165.  
  166.         }
  167.  
  168.         private String driverClass;
  169.         private String url;
  170.         private String username;
  171.         private String password;
  172.  
  173.         private int minConns = 5;
  174.         private int maxConns = 20;
  175.         private static int isUsed = 0;
  176.         private int timeout = 1000;
  177.  
  178.         // 构建定时器:自动关闭超时的连接.
  179.  
  180.         /**
  181.          * 获取连接
  182.          */
  183.         public static int Try_Time = 0;
  184.  
  185.         // 只有这个构造方法
  186.         public DbConnectionPool(String driverClass, String url, String username, String password, int minConns, int maxConns) {
  187.                 this.driverClass = driverClass;
  188.                 this.url = url;
  189.                 this.username = username;
  190.                 this.password = password;
  191.                 this.minConns = minConns;
  192.                 this.maxConns = maxConns;
  193.                 initConnection();
  194.         }
  195.  
  196.         private Connection createNewConnection() {
  197.  
  198.                 try {
  199.                         Connection conn = null;
  200.                         conn = DriverManager.getConnection(url, username, password);
  201.                         if (LogUtil.isInfo()) {
  202.                                 logger.info("创建了一个新的链接");
  203.                         }
  204.  
  205.                         if (conn != null) {
  206.                                 return conn;
  207.                         }
  208.                 } catch (SQLException e) {
  209.                         if (LogUtil.isInfo()) {
  210.                                 logger.info("获取数据库连接失败" + e);
  211.                         }
  212.  
  213.                 }
  214.                 // 使用连接数有可能数据库已经达到最大的连接
  215.                 return null;
  216.         }
  217.  
  218.         /**
  219.          * 释放连接入连接池
  220.          */
  221.         public synchronized void freeConnection(Connection conn) throws SQLException {
  222.                 if (conn != null && !conn.isClosed()) {
  223.                         freeConnections.add(conn);
  224.                         busyConnectionsMap.remove(conn.toString().trim());
  225.                         if (isUsed >= 1) {
  226.                                 isUsed--;
  227.                         }
  228.                         notifyAll();
  229.                         if (LogUtil.isInfo()) {
  230.                                 logger.info("释放连接!");
  231.                         }
  232.  
  233.                 }
  234.  
  235.         }
  236.  
  237.         public synchronized Connection getConnection() {
  238.                 if (LogUtil.isInfo()) {
  239.                         System.out.println("[系统报告]:已用 " + isUsed + " 个连接,空闲连接个数 " + freeConnections.size());
  240.                 }
  241.                 // ==========第一种情况
  242.                 if (freeConnections.size() >= 1) {
  243.                         if (LogUtil.isInfo) {
  244.                                 System.out.println("[it has free connections]");
  245.                         }
  246.  
  247.                         Connection conn = freeConnections.firstElement();
  248.                         try {
  249.                                 if (conn.isClosed() || conn == null) {
  250.                                         // 新的连接代替无效连接
  251.                                         conn = createNewConnection();
  252.                                 }
  253.                         } catch (SQLException e) {
  254.                                 conn = createNewConnection();
  255.                         }
  256.                         freeConnections.removeElementAt(0);
  257.                         isUsed++;
  258.                         // 记住内存地址
  259.                         busyConnectionsMap.put(conn.toString().trim(), new ConnectionAndStartTime(conn, new Date().getTime()));
  260.                         return conn;
  261.                 }
  262.  
  263.                 if (freeConnections.size() <= 0) {
  264.                         if (LogUtil.isInfo()) {
  265.                                 System.out.println("[now it is getting connection from db]");
  266.                         }
  267.  
  268.                         // ==========第二种情况.1
  269.                         if (isUsed < maxConns) {
  270.                                 Connection conn = createNewConnection();
  271.                                 if (conn != null) {
  272.                                         isUsed++;
  273.                                         busyConnectionsMap.put(conn.toString().trim(), new ConnectionAndStartTime(conn, new Date().getTime()));
  274.                                         return conn;
  275.                                 } else {
  276.                                         // 再次自身调用自己:可能已经有空的连接存在
  277.                                         return getConnection();
  278.                                 }
  279.  
  280.                         }
  281.                         // ==========第二种情况.2
  282.                         if (isUsed >= maxConns) {
  283.                                 if (LogUtil.isInfo) {
  284.                                         System.out.println("it has no more connections that is allowed for use");
  285.                                 }
  286.  
  287.                                 Try_Time++;
  288.                                 if (LogUtil.isInfo) {
  289.                                         System.out.println("***[第" + Try_Time + "尝试从新获取连接]***");
  290.                                 }
  291.  
  292.                                 if (Try_Time > 10) {
  293.                                         // throw new RuntimeException("***[从新获取数据库连接的失败次数过多]***");
  294.                                         // 多次不能获得连接则返回null
  295.                                         if (LogUtil.isInfo()) {
  296.                                                 System.out.println("重复尝试获取数据库连接10次...???等待解决问题");
  297.                                         }
  298.                                         return null;
  299.                                 }
  300.                                 // 连接池已满
  301.                                 long startTime = System.currentTimeMillis();
  302.                                 try {
  303.                                         wait(timeout);
  304.                                 } catch (InterruptedException e) {
  305.                                         // e.printStackTrace();
  306.                                 }
  307.                                 if (new Date().getTime() - startTime > timeout) {
  308.                                         if (LogUtil.isInfo()) {
  309.                                                 logger.info("***[没有可获取的链接,正在重试...]***");
  310.                                         }
  311.  
  312.                                         // 再次自身调用自己
  313.                                         Connection conn = getConnection();
  314.                                         if (conn != null) {
  315.                                                 busyConnectionsMap.put(conn.toString(), new ConnectionAndStartTime(conn, new Date().getTime()));
  316.                                                 return conn;
  317.                                         } else {
  318.                                                 // 再次自身调用自己
  319.                                                 return getConnection();
  320.                                         }
  321.                                 }
  322.                         }
  323.  
  324.                 }
  325.                 return null;
  326.  
  327.         }
  328.  
  329.         private synchronized void initConnection() {
  330.                 try {
  331.                         Class.forName(driverClass); // 加载驱动
  332.                         for (int i = 0; i < minConns; i++) {
  333.                                 Connection conn = createNewConnection();
  334.                                 if (conn != null) {
  335.                                         freeConnections.add(conn);
  336.                                 } else {
  337.                                         throw new RuntimeException("获取的数据库连接为null");
  338.                                 }
  339.  
  340.                         }
  341.                         if (LogUtil.isInfo()) {
  342.                                 logger.info("初始化数据库" + minConns + "个连接放入连接池\n");
  343.                         }
  344.  
  345.                 } catch (ClassNotFoundException e) {
  346.                         if (LogUtil.isInfo()) {
  347.                                 logger.info("驱动无法加载,请检查驱动是否存在,driver: " + driverClass + e + "\n");
  348.                         }
  349.                 }
  350.         }
  351.  
  352.         public synchronized void releaseAll() {
  353.                 Enumeration<Connection> enums = freeConnections.elements();
  354.                 while (enums.hasMoreElements()) {
  355.                         try {
  356.                                 enums.nextElement().close();
  357.                         } catch (SQLException e) {
  358.                                 if (LogUtil.isInfo()) {
  359.                                         logger.info("关闭链接失败" + e);
  360.                                 }
  361.  
  362.                         }
  363.                 }
  364.                 freeConnections.removeAllElements();
  365.                 busyConnectionsMap.clear();
  366.                 if (LogUtil.isInfo()) {
  367.                         logger.info("释放了所有的连接");
  368.                 }
  369.  
  370.         }
  371.  
  372. }
  373.  
  374. /**
  375.  *
  376.  * 记录连接使用的时间
  377.  *
  378.  */
  379. class ConnectionAndStartTime {
  380.         private Connection conn;
  381.  
  382.         private long startTime;
  383.  
  384.         public ConnectionAndStartTime(Connection conn, long startTime) {
  385.                 super();
  386.                 this.conn = conn;
  387.                 this.startTime = startTime;
  388.         }
  389.  
  390.         public Connection getConn() {
  391.                 return conn;
  392.         }
  393.  
  394.         public long getStartTime() {
  395.                 return startTime;
  396.         }
  397.  
  398.         public void setConn(Connection conn) {
  399.                 this.conn = conn;
  400.         }
  401.  
  402.         public void setStartTime(long startTime) {
  403.                 this.startTime = startTime;
  404.         }
  405. }
  406.  
  407. /**
  408.  *
  409.  * 记录日志
  410.  *
  411.  */
  412. class LogUtil {
  413.         public static boolean isDebug = true;
  414.         public static boolean isInfo = true;
  415.  
  416.         public static boolean isDebug() {
  417.                 return isDebug;
  418.         }
  419.  
  420.         public static boolean isInfo() {
  421.                 return isInfo;
  422.         }
  423.  
  424. }
  425.  
  426. /src/org/apple/connectionpool/connectionpoll.properties
  427. driverClass=oracle.jdbc.driver.OracleDriver
  428. url=jdbc\:oracle\:thin\:@172.18.2.95\:1521\:MYSQL
  429. username=wjt
  430. password=wjt
  431. minConns=1
  432. maxConns=3
  433.  
  434.  
  435. package com.etc.oa.util;
  436.  
  437. import java.sql.Connection;
  438. import java.sql.PreparedStatement;
  439. import java.sql.ResultSet;
  440. import java.sql.SQLException;
  441.  
  442. import org.apple.connectionpool.DbConnectionManager;
  443.  
  444. public class DBUtil {
  445.  
  446.         // ==================================================
  447.         public static Connection getConnection() {
  448.                
  449.                 Connection conn = null;
  450.                 conn = DbConnectionManager.getInstance().getConnection();
  451.                 //conn = DriverManager.getConnection("jdbc:oracle:thin:@172.18.2.95:1521:MYSQL", "wjt", "wjt");
  452.                 return conn;
  453.                
  454.                
  455.         }
  456.  
  457.         // ==================================================
  458.         /**
  459.          * 建立PreparedStatement实例
  460.          */
  461.         public static PreparedStatement createPreparedStatement(Connection conn, String sql) throws SQLException {
  462.                 try {
  463.                         if (sql != null && conn != null) {
  464.                                 PreparedStatement pstmt = conn.prepareStatement(sql);
  465.                                 if (pstmt != null) {
  466.                                         return pstmt;
  467.                                 }
  468.                         }
  469.                 } catch (SQLException e) {
  470.                         throw e;
  471.  
  472.                 }
  473.                 return null;
  474.  
  475.         }
  476.  
  477.         /**
  478.          * pstmt更新操作
  479.          */
  480.         public static int pstmtExcuteUpdate(PreparedStatement pst) throws SQLException {
  481.                 try {
  482.                         if (pst != null) {
  483.                                 return pst.executeUpdate();
  484.                         }
  485.                 } catch (SQLException e) {
  486.                         throw e;
  487.  
  488.                 }
  489.                 return 0;
  490.  
  491.         }
  492.  
  493.         // ==================================================
  494.  
  495.         // ==================================================
  496.         /**
  497.          * pstmt查询操作
  498.          */
  499.         public static ResultSet pstmtExcuteQuery(PreparedStatement pst) throws SQLException {
  500.                 try {
  501.                         if (pst != null) {
  502.                                 ResultSet rs = pst.executeQuery();
  503.                                 if (rs != null) {
  504.                                         return rs;
  505.                                 }
  506.                         }
  507.                 } catch (SQLException e) {
  508.                         throw e;
  509.                 }
  510.                 return null;
  511.         }
  512.  
  513.         // ====================================================
  514.  
  515.         // ====================================================
  516.         public static void close(Connection conn) throws SQLException {
  517.                 DbConnectionManager.getInstance().close(conn);
  518.         }
  519.  
  520.         public static void close(PreparedStatement pst) throws SQLException {
  521.                 if (pst != null) {
  522.                         try {
  523.                                 pst.close();
  524.                         } catch (SQLException e) {
  525.                                 throw e;
  526.                         }
  527.                 }
  528.         }
  529.  
  530.         public static void close(ResultSet rs) throws SQLException {
  531.                 if (rs != null) {
  532.                         try {
  533.                                 rs.close();
  534.                         } catch (SQLException e) {
  535.                                 throw e;
  536.                         }
  537.                 }
  538.         }
  539.  
  540.         // =========================================================
  541.         /**
  542.          * 快速关闭资源ResultSet rs, PreparedStatement pstmt, Connection conn
  543.          */
  544.         public static void close(ResultSet rs, PreparedStatement pst, Connection conn) throws SQLException {
  545.                 if (rs != null) {
  546.                         try {
  547.                                 rs.close();
  548.                         } catch (SQLException e) {
  549.                                 throw e;
  550.                         }
  551.                 }
  552.                 if (pst != null) {
  553.                         try {
  554.                                 pst.close();
  555.                         } catch (SQLException e) {
  556.                                 throw e;
  557.                         }
  558.                 }
  559.                 if (conn != null) {
  560.                         DbConnectionManager.getInstance().close(conn);
  561.                 }
  562.  
  563.         }
  564.  
  565.         /**
  566.          * 快速关闭资源ResultSet rs, PreparedStatement pstmt
  567.          */
  568.         public static void close(ResultSet rs, PreparedStatement pst) throws SQLException {
  569.                 if (rs != null) {
  570.                         try {
  571.                                 rs.close();
  572.                         } catch (SQLException e) {
  573.                                 throw e;
  574.                         }
  575.                 }
  576.                 if (pst != null) {
  577.                         try {
  578.                                 pst.close();
  579.                         } catch (SQLException e) {
  580.                                 throw e;
  581.                         }
  582.                 }
  583.  
  584.         }
  585.  
  586.         /**
  587.          * 快速关闭资源PreparedStatement pstmt, Connection conn
  588.          */
  589.         public static void close(PreparedStatement pst, Connection conn) throws SQLException {
  590.                 if (pst != null) {
  591.                         try {
  592.                                 pst.close();
  593.                         } catch (SQLException e) {
  594.                                 throw e;
  595.                         }
  596.                 }
  597.                 if (conn != null) {
  598.                         DbConnectionManager.getInstance().close(conn);
  599.                 }
  600.  
  601.         }
  602.  
  603.         // =========================================================
  604.  
  605.         // =========================================================
  606.         /**
  607.          * 事务处理
  608.          */
  609.         public static void rollback(Connection conn) throws SQLException {
  610.                 if (conn != null) {
  611.                         try {
  612.                                 conn.rollback();
  613.                         } catch (SQLException e) {
  614.                                 throw e;
  615.                         }
  616.                 }
  617.         }
  618.  
  619.         public static void commit(Connection conn) throws SQLException {
  620.                 if (conn != null) {
  621.                         try {
  622.                                 conn.commit();
  623.                         } catch (SQLException e) {
  624.                                 throw e;
  625.                         }
  626.                 }
  627.         }
  628.  
  629.         public static void setCommit(Connection conn, Boolean value) throws SQLException {
  630.                 if (conn != null) {
  631.                         try {
  632.                                 conn.setAutoCommit(value);
  633.                         } catch (SQLException e) {
  634.                                 throw e;
  635.                         }
  636.                 }
  637.         }
  638.  
  639.         public static void main(String[] args) throws SQLException {
  640.                 Connection connection4 = DbConnectionManager.getInstance().getConnection();
  641.                 DbConnectionManager.getInstance().close(connection4);
  642.                 Connection connectiona = DbConnectionManager.getInstance().getConnection();
  643.                 Connection connectionb = DbConnectionManager.getInstance().getConnection();
  644.                 Connection connectionc = DbConnectionManager.getInstance().getConnection();
  645.                 for (int i = 0; i < 10; i++) {
  646.                         Connection connection8 = DbConnectionManager.getInstance().getConnection();
  647.                         DbConnectionManager.getInstance().close(connection8);
  648.                 }
  649.  
  650.         }
  651. }
  652.  
  653. //java/5398

回复 "Java实现简单的数据库连接池代码"

这儿你可以回复上面这条便签

captcha