日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

数据库连接池的设计思路及java实现

發布時間:2025/3/8 数据库 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据库连接池的设计思路及java实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

connectionPool.DBConnectionManager

[java]?view plain?copy

  • package?connectionPool;??
  • ??
  • import?java.sql.Connection;??
  • import?java.sql.Driver;??
  • import?java.sql.DriverManager;??
  • import?java.sql.SQLException;??
  • import?java.util.ArrayList;??
  • import?java.util.Enumeration;??
  • import?java.util.HashSet;??
  • import?java.util.Hashtable;??
  • import?java.util.List;??
  • import?java.util.Map;??
  • import?java.util.Map.Entry;??
  • import?java.util.Set;??
  • ??
  • import?connectionPool.util.Logger;??
  • import?connectionPool.util.PropertiesMgr;??
  • ??
  • /**?
  • ?*?連接池的設計思路?
  • ?*?1、?
  • ?*?初始化固定數目的連接(空閑連接與活躍連接在同一池中),建立連接的代理類,添加busy與startTime屬性以便分發與回收連接?
  • ?*?另建立守護線程回收失效連接?
  • ?*?2、?
  • ?*?維護一空閑連接池,初始為空,需要連接時建立,用完的連接回收進入空閑連接池;?
  • ?*?后續所需連接從空閑連接池獲取;activeNum記錄活躍連接數目;?
  • ?*?當空閑連接池為空且活躍連接數達到上限時,請求等待,超時即獲取連接失敗,超時前有連接被釋放方可獲得連接?
  • ?*?第二個設計巧妙優勢明顯,采用第二種方式?
  • ?*??
  • ?*?數據庫連接管理類,單例模式?
  • ?*?可以管理加載多個數據庫驅動,維護多個數據庫連接池?
  • ?*?@author?shijin?
  • ?*?
  • ?*/??
  • public?class?DBConnectionManager?{??
  • ??????
  • ????private?static?DBConnectionManager?dbm?=?null;??
  • ??????
  • ????//單例模式里的成員變量都相當于是static了???
  • ????/**?
  • ?????*?客戶數目?
  • ?????*/??
  • ????private?static?int?clients?=?0;??
  • ????/**?
  • ?????*?加載的驅動器集合?
  • ?????*/??
  • ????private?Set<Driver>?drivers?=?new?HashSet<Driver>();??
  • ????/**?
  • ?????*?數據庫連接池字典?
  • ?????*/??
  • ????private?Hashtable<String,DBConnectionPool>?pools?=?new?Hashtable<String,DBConnectionPool>();??
  • ??????
  • ????private?final?Logger?log?=?Logger.getInstance(DBConnectionPool.class);??
  • ??????
  • ????private?DBConnectionManager()?{??
  • ????????loadDrivers();??
  • ????????createPools();??
  • ????}??
  • ??
  • ????/**?
  • ?????*?裝載和注冊所有的JDBC驅動程序?
  • ?????*/??
  • ????private?void?loadDrivers()?{??
  • ????????String?str_drivers?=?PropertiesMgr.getProperty("driver");??
  • ????????for(String?str_driver:str_drivers.split("\\s"))?{??
  • ????????????Driver?driver?=?null;??
  • ????????????try?{??
  • ????????????????driver?=?(Driver)Class.forName(str_driver).newInstance();??
  • ????????????????DriverManager.registerDriver(driver);??
  • ????????????????log.info("成功加載JDBC驅動:"?+?str_driver);??
  • ????????????}?catch?(InstantiationException?e)?{??
  • ????????????????log.error("加載JDBC驅動"?+?str_driver?+?"時初始化異常,請檢查配置文件");??
  • ????????????}?catch?(IllegalAccessException?e)?{??
  • ????????????????log.info("加載JDBC驅動"?+?str_driver?+?"時非法訪問,請檢查配置文件");??
  • ????????????}?catch?(ClassNotFoundException?e)?{??
  • ????????????????log.info("未找到JDBC驅動"?+?str_driver?+?"請引入相關包");??
  • ????????????}?catch?(SQLException?e)?{??
  • ????????????????log.info("加載JDBC驅動"?+?str_driver?+?"失敗,請檢查引入包的正確性");??
  • ????????????}??
  • ????????????drivers.add(driver);??
  • ????????}??
  • ????}??
  • ??
  • ????/**?
  • ?????*?根據配置文件創建數據庫連接池?
  • ?????*/??
  • ????private?void?createPools()?{??
  • ????????Enumeration<?>?elements?=?PropertiesMgr.propertiesNames();??
  • ????????while(elements.hasMoreElements())?{??
  • ????????????String?element?=?(String)elements.nextElement();??
  • ????????????if(element.endsWith(".url"))?{??
  • ????????????????String?poolName?=?element.substring(0,?element.lastIndexOf("."));??
  • ????????????????String?url?=?PropertiesMgr.getProperty(poolName?+?".url");??
  • ????????????????if(url?==?null)?{??
  • ????????????????????log.error("無法連接到數據庫"?+?poolName?+?"請檢查配置文件連接字符串");??
  • ????????????????????continue;??
  • ????????????????}??
  • ????????????????String?user?=?PropertiesMgr.getProperty(poolName?+?".user");??
  • ????????????????String?pwd?=?PropertiesMgr.getProperty(poolName?+?".password");??
  • ????????????????String?str_max?=?PropertiesMgr.getProperty(poolName?+?".maxconn",?"0");??
  • ????????????????int?maxConn?=?0;??
  • ????????????????try{??
  • ????????????????????maxConn?=?Integer.parseInt(str_max);??
  • ????????????????}catch(NumberFormatException?e)?{??
  • ????????????????????log.error("數據庫"?+?poolName?+?"最大連接數設置錯誤,默認設為20");??
  • ????????????????????maxConn?=?20;??
  • ????????????????}?????????????????
  • ????????????????DBConnectionPool?pool?=?new?DBConnectionPool(maxConn,url,poolName,user,pwd);??
  • ????????????????pools.put(poolName,?pool);??
  • ????????????????log.info("成功創建數據庫連接池"?+?poolName);??
  • ????????????}??
  • ????????}??
  • ????}??
  • ??
  • ????/**?
  • ?????*?獲得單例?
  • ?????*?@return?DBConnectionManager單例?
  • ?????*/??
  • ????public?synchronized?static?DBConnectionManager?getInstance()?{??
  • ????????if(dbm?==?null)?{??
  • ????????????dbm?=?new?DBConnectionManager();??
  • ????????}??
  • ????????clients++;??
  • ????????return?dbm;??
  • ????}??
  • ??
  • ????/**?
  • ?????*?從指定連接池中獲取可用連接,無等待?
  • ?????*?@param?poolName??要獲取連接的連接池名稱?
  • ?????*?@return??連接池中的一個可用連接或null?
  • ?????*/??
  • ????public?Connection?getConnection(String?poolName)?{??
  • ????????DBConnectionPool?pool?=?(DBConnectionPool)pools.get(poolName);??
  • ????????return?pool.getConnection();??
  • ????}??
  • ??????
  • ????/**?
  • ?????*?從指定的連接池獲取可用連接,有等待超時?
  • ?????*?@param?poolName??要獲取連接的連接池名稱?
  • ?????*?@param?timeout???獲取可用連接的超時時間,單位為秒?
  • ?????*?@return??????????連接池中的一個可用連接或null?
  • ?????*/??
  • ????public?Connection?getConnection(String?poolName,long?timeout)?{??
  • ????????DBConnectionPool??pool?=?(DBConnectionPool)pools.get(poolName);??
  • ????????return?pool.getConnection(timeout);??
  • ????}??
  • ??????
  • ????/**?
  • ?????*?回收指定連接池的連接?
  • ?????*?@param?poolName??連接池名稱?
  • ?????*?@param?conn??????要回收的連接?
  • ?????*/??
  • ????public?void?freeConnection(String?poolName,Connection?conn)?{??
  • ????????DBConnectionPool?pool?=?(DBConnectionPool)pools.get(poolName);??
  • ????????if(pool?!=?null)?{??
  • ????????????pool.freeConnection(conn);??
  • ????????}??
  • ????????log.error("找不到連接池,無法回收,請檢查參數");??
  • ????}??
  • ??????
  • ????/**?
  • ?????*?關閉所有連接,撤銷驅動器的注冊?
  • ?????*/??
  • ????public?synchronized?void?release()?{??
  • ????????//所有客戶連接都關閉時才真正關閉連接撤銷注冊??
  • ????????if(clients--?!=?0)?{??
  • ????????????return;??
  • ????????}??
  • ????????for(Map.Entry<String,DBConnectionPool>?poolEntry:pools.entrySet())?{??
  • ????????????DBConnectionPool?pool?=?poolEntry.getValue();??
  • ????????????pool.releaseAll();??
  • ????????}??
  • ????????log.info("已經關閉所有連接");??
  • ????????for(Driver?driver:drivers)?{??
  • ????????????try?{??
  • ????????????????DriverManager.deregisterDriver(driver);??
  • ????????????????log.info("撤銷JDBC驅動器"?+?driver.getClass().getName()?+?"的注冊");??
  • ????????????}?catch?(SQLException?e)?{??
  • ????????????????log.error("撤銷JDBC驅動器"?+?driver.getClass().getName()?+?"的注冊異常");??
  • ????????????}??
  • ????????}??
  • ????????log.info("驅動器撤銷完成");??
  • ????}??
  • ??????
  • ????/**?
  • ?????*?此內部類定義了一個連接池.?
  • ?????*?它能夠獲取數據庫連接,直到預定的最?大連接數為止?
  • ?????*?在返回連接給客戶程序之前,它能夠驗證連接的有效性?
  • ?????*?@author?shijin?
  • ?????*/??
  • ????private?class?DBConnectionPool?{??
  • ????????private?int?activeNum?=?0;??
  • ????????private?int?maxConn?=?0;??
  • ????????private?String?url?=?null;??
  • ????????private?String?poolName?=?null;??
  • ????????private?String?user?=?null;??
  • ????????private?String?pwd?=?null;??
  • ????????private?List<Connection>?freeConnections?=?new?ArrayList<Connection>();??
  • ??????????
  • ????????/**?
  • ?????????*??
  • ?????????*?@param?maxConn???設定的連接池允許的最大連接數?
  • ?????????*?@param?url???????數據庫連接url?
  • ?????????*?@param?poolName??連接池名稱?
  • ?????????*?@param?user??????數據庫用戶名,或null?
  • ?????????*?@param?pwd???????數據庫用戶密碼,或null?
  • ?????????*/??
  • ????????public?DBConnectionPool(int?maxConn,?String?url,?String?poolName,??
  • ????????????????String?user,?String?pwd)?{??
  • ????????????super();??
  • ????????????this.maxConn?=?maxConn;??
  • ????????????this.url?=?url;??
  • ????????????this.poolName?=?poolName;??
  • ????????????this.user?=?user;??
  • ????????????this.pwd?=?pwd;??
  • ????????}??
  • ??????????
  • ????????/**?
  • ?????????*?獲得一個可用連接,不保證任何情況都能返回一個連接(比如超過最大連接數的時候返回null)?
  • ?????????*?1、若空閑連接池不為空,從空閑連接池取出一個連接后檢查有效性,正常則返回,失效則重新獲取連接?
  • ?????????*?2、若空閑連接池為空且未超過最大連接數限制,新建一個連接并返回?
  • ?????????*?3、空閑連接數為空且超過最大連接數限制,返回null?
  • ?????????*?@return??獲得的可用連接?
  • ?????????*/??
  • ????????public?synchronized?Connection?getConnection()?{??
  • ????????????Connection?conn?=?null;??
  • ????????????//空閑連接池中有空閑連接,直接取??
  • ????????????if(freeConnections.size()?>?0)?{??
  • ????????????????//從空閑連接池中取出一個連接??
  • ????????????????conn?=?freeConnections.get(0);??
  • ????????????????freeConnections.remove(0);??
  • ????????????????//檢測連接有效性??
  • ????????????????try{??
  • ????????????????????if(conn.isClosed())?{??
  • ????????????????????????//由于已經從空閑連接池取出,所以不使用無效連接其就無法重新進入??
  • ????????????????????????//空閑連接池,意味著其已經被刪除了,記入日志即可??
  • ????????????????????????log.info("從連接池"?+?poolName?+?"中取出的連接已關閉,重新獲取連接");??
  • ????????????????????????//繼續從連接池嘗試獲取連接??
  • ????????????????????????conn?=?getConnection();??
  • ????????????????????}??
  • ????????????????}catch(SQLException?e)?{??
  • ????????????????????log.info("從連接池"?+?poolName?+?"中取出的發生服務器訪問錯誤,重新獲取連接");??
  • ????????????????????conn?=?getConnection();??
  • ????????????????}??
  • ????????????}?else?if(activeNum?<?maxConn)?{??
  • ????????????????conn?=?newConnection();??
  • ????????????}?else?{??
  • ????????????????//未獲得連接??
  • ????????????}??
  • ????????????if(conn?!=?null)?{??
  • ????????????????activeNum++;??
  • ????????????}??
  • ????????????return?conn;??
  • ????????}??
  • ??????????
  • ????????/**?
  • ?????????*?當無空閑連接而又未達到最大連接數限制時創建新的連接?
  • ?????????*?@return??新創建的連接?
  • ?????????*/??
  • ????????private?Connection?newConnection()?{??
  • ????????????Connection?conn?=?null;??
  • ????????????try{??
  • ????????????????if(user?==?null)?{??
  • ????????????????????conn?=?DriverManager.getConnection(url);??
  • ????????????????}?else?{??
  • ????????????????????conn?=?DriverManager.getConnection(url,?user,?pwd);??
  • ????????????????}??
  • ????????????????log.info("與數據庫"?+?poolName?+?"創建一個新連接");??
  • ????????????}catch(SQLException?e)?{??
  • ????????????????log.error("無法根據\""?+?url?+?"\"與數據庫"?+?poolName?+?"建立新連接");??
  • ????????????}??
  • ????????????return?conn;??
  • ????????}??
  • ??????????
  • ????????/**?
  • ?????????*?獲得一個可用連接,超過最大連接數時線程等待,直到有有連接釋放時返回一個可用連接或者超時返回null?
  • ?????????*?@param?timeout?等待連接的超時時間,單位為秒?
  • ?????????*?@return?
  • ?????????*/??
  • ????????public?synchronized?Connection?getConnection(long?timeout)?{??
  • ????????????Connection?conn?=?null;??
  • ????????????long?startTime?=?System.currentTimeMillis();??
  • ????????????while((conn?=?getConnection())?==?null)?{??
  • ????????????????try{??
  • ????????????????????//被notify(),notifyALL()喚醒或者超時自動蘇醒??
  • ????????????????????wait(timeout);??
  • ????????????????}catch(InterruptedException?e)?{??
  • ????????????????????log.error("等待連接的線程被意外打斷");??
  • ????????????????}??
  • ????????????????//若線程在超時前被喚醒,則不會返回null,繼續循環嘗試獲取連接??
  • ????????????????if(System.currentTimeMillis()?-?startTime?>?timeout*1000000)??
  • ????????????????????return?null;??
  • ????????????}??
  • ????????????return?conn;??
  • ????????}??
  • ??????????
  • ????????/**?
  • ?????????*?將釋放的空閑連接加入空閑連接池,活躍連接數減一并激活等待連接的線程?
  • ?????????*?@param?conn??釋放的連接?
  • ?????????*/??
  • ????????public?synchronized?void?freeConnection(Connection?conn)?{??
  • ????????????freeConnections.add(conn);??
  • ????????????activeNum--;??
  • ????????????notifyAll();//通知正在由于達到最大連接數限制而wait的線程獲取連接??
  • ????????}??
  • ??????????
  • ????????/**?
  • ?????????*?關閉空閑連接池中的所有連接?
  • ?????????*/??
  • ????????public?synchronized?void?releaseAll()?{??
  • ????????????for(Connection?conn:freeConnections)?{??
  • ????????????????try{??
  • ????????????????????conn.close();??
  • ????????????????????log.info("關閉空閑連接池"?+?poolName?+?"中的一個連接");??
  • ????????????????}catch(SQLException?e)?{??
  • ????????????????????log.error("關閉空閑連接池"?+?poolName?+?"中的連接失敗");??
  • ????????????????}??
  • ????????????}??
  • ????????????freeConnections.clear();??
  • ????????}??
  • ????}??
  • }??
  • connectionpool.util.Logger

    [java]?view plain?copy

  • package?connectionPool.util;??
  • ??
  • import?java.io.FileWriter;??
  • import?java.io.IOException;??
  • import?java.io.PrintWriter;??
  • import?java.util.Date;??
  • ??
  • /**?
  • ?*?日志文件創建維護類,單例模式?
  • ?*?@author?shijin?
  • ?*?
  • ?*/??
  • public?class?Logger?{??
  • ??????
  • ????private?static?Logger?logger=?null;??
  • ????private?PrintWriter?log?=?null;??
  • ????private?static?int?level?=?0;??
  • ????private?Class<?>?c?=?null;??
  • ????private?static?final?int?DEBUGLEVEL?=?1;??
  • ????private?static?final?int?INFOLEVEL?=?2;??
  • ????private?static?final?int?ERRORLEVEL?=?3;??
  • ??????
  • ????private?Logger(Class<?>?c)?{??
  • ????????String?logFileName?=?PropertiesMgr.getProperty("logfile","DBlog.txt");??
  • ????????String?str_level?=?PropertiesMgr.getProperty("loglevel",?"3");??
  • ????????this.c?=?c;??
  • ????????level?=?Integer.parseInt(str_level);??
  • ????????try?{??
  • ????????????log?=?new?PrintWriter(new?FileWriter(logFileName),true);??
  • ????????}?catch?(IOException?e)?{??
  • ????????????System.err.println("無法打開日志文件"?+?logFileName);??
  • ????????????log?=?new?PrintWriter(System.err);??
  • ????????}??
  • ????}??
  • ??????
  • ????public?synchronized?static?Logger?getInstance(Class<?>?c)?{??
  • ????????if(logger?==?null)?{??
  • ????????????logger?=?new?Logger(c);??
  • ????????}??
  • ????????return?logger;??
  • ????}??
  • ??????
  • ??????
  • ????public?void?debug(String?msg)?{??
  • ????????if(level?>?DEBUGLEVEL)?{??
  • ????????????msg?=?"DEBUG:"?+?new?Date()?+?"-"?+?msg;??
  • ????????????System.out.println(msg);??
  • ????????????log.println(msg);??
  • ????????}??
  • ??????????????
  • ????}??
  • ??????
  • ????public?void?info(String?msg)?{??
  • ????????if(level?>?INFOLEVEL)?{??
  • ????????????msg?=?"INFO:"?+?new?Date()?+?"-"?+?msg;??
  • ????????????System.out.println(msg);??
  • ????????????log.println(msg);??
  • ????????}??
  • ??????????????
  • ????}??
  • ??????
  • ????public?void?error(String?msg)?{??
  • ????????if(level?>?ERRORLEVEL)?{??
  • ????????????msg?=?"ERROR:"?+?new?Date()?+?"-"?+?c?+?"-"?+?msg;??
  • ????????????System.out.println(msg);??
  • ????????????log.println(msg);??
  • ????????}??
  • ????}??
  • }??
  • connection.util.PropertiesMgr

    [java]?view plain?copy

  • package?connectionPool.util;??
  • ??
  • import?java.io.File;??
  • import?java.io.IOException;??
  • import?java.util.Enumeration;??
  • import?java.util.Properties;??
  • /**?
  • ?*?屬性文件加載管理類,單例模式?
  • ?*?@author?shijin?
  • ?*?
  • ?*/??
  • public?class?PropertiesMgr?{??
  • ????private?static?Properties?pro?=?new?Properties();??
  • ????private?PropertiesMgr(){}??
  • ????static?{??
  • ????????try?{??
  • ????????????pro.load(PropertiesMgr.class.getClassLoader().getResourceAsStream("config"?+?File.separator?+?"DB.properties"));??
  • ????????}?catch?(IOException?e)?{??
  • ????????????e.printStackTrace();??
  • ????????}??
  • ????}??
  • ??????
  • ????public?static?String?getProperty(String?key)?{??
  • ????????return?pro.getProperty(key);??
  • ????}??
  • ??????
  • ????public?static?String?getProperty(String?key,String?defaultValue)?{??
  • ????????//找不到key用defaultValue,而不是說后面為空字符串采用defaultValue??
  • ????????return?pro.getProperty(key,?defaultValue);??
  • ????}??
  • ??????
  • ????public?static?Enumeration<?>?propertiesNames()?{??
  • ????????return?pro.propertyNames();??
  • ????}??
  • }??
  • DB.properties

    [plain]?view plain?copy

  • driver=com.mysql.jdbc.Driver??
  • ??
  • mysql.url=jdbc:mysql://127.0.0.1/caiwu?useUnicode=true&characterEncoding=gb2312??
  • ??
  • mysql.user=root??
  • ??
  • mysql.password=123??
  • ??
  • mysql.maxconn=1000??
  • ??
  • #\u65E5\u5FD7\u6587\u4EF6\u7684\u540D\u79F0??
  • logfile=??
  • #\u65E5\u5FD7\u7EA7\u522B??
  • loglevel=??
  • 轉載于:https://my.oschina.net/newchaos/blog/1555846

    創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

    以上是生活随笔為你收集整理的数据库连接池的设计思路及java实现的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。