国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

連接池鏈接超時(shí)

2019-11-08 20:40:43
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

數(shù)據(jù)庫(kù)連接池中的connection在八小時(shí)內(nèi)沒(méi)有被用到,則會(huì)自動(dòng)斷開(kāi)連接,那么怎么處理數(shù)據(jù)庫(kù)連接超時(shí)的問(wèn)題?

         我在自己寫(xiě)mybatis框架的時(shí)候,這樣處理的:首先確保連接池中有指定數(shù)量的鏈接:將connection和創(chuàng)建時(shí)間System.currentTimeMillis()以鍵值對(duì)的形式存放在map集合中,用一個(gè)定時(shí)器,每隔1小時(shí)檢查一下連接數(shù)目,數(shù)目大于指定個(gè)數(shù),則從map中移除,小于指定個(gè)數(shù),則加入新的鏈接。其次:檢查連接在7個(gè)小時(shí)內(nèi)是否被用,如果沒(méi)有被用,則執(zhí)行一個(gè)sql語(yǔ)句:String sql = "drop table if exists tables";將connection對(duì)象重新加入到map集合中。

我的代碼:

public class ConnectionFacory{

         PRivate static ConnectionFacory instance;

         private static DBConn dbConn = new DBConn();//獲取鏈接的類(lèi)

         private static String fileName = null;//數(shù)據(jù)庫(kù)的文件名,先為null,初始化對(duì)象后改為傳入的值

        

         /**

          * 需要知道連接池中的連接是否被使用。

          * 如果用Map<Connection,time>的數(shù)據(jù)類(lèi)型去保存

          * time為初始化連接的毫秒值,沒(méi)有使用過(guò)的話設(shè)置為0.

          * 從數(shù)據(jù)庫(kù)獲取時(shí),設(shè)置獲取當(dāng)前的時(shí)間毫秒值。

          * 并把這個(gè)連接加入到另一個(gè)連接池中

          *

          */

         private static Map<Connection,Long> connectionPool =new HashMap<Connection,Long>();

        

         /**

          * 設(shè)置最大時(shí)間為一個(gè)常量

          */

          public static finallong MAX_UNUSED_TIME = 7 * 60 *60 * 1000;

        

         /**

          * 使用的連接都加入到這個(gè)連接池中

          */

         private static Map<Connection,Long> connectionUsePool= new HashMap<Connection,Long>();

        

         private ConnectionFacory(){

         }

        

         public static synchronized ConnectionFacorygetInstance(String fileName){

                   if(instance == null){

                            instance = new ConnectionFacory();

                           

                            ConnectionFacory.fileName = fileName;//屬于共享數(shù)據(jù)

                            initPool(20);

                            timer();

                   }

                  

                   return instance;

         }

 

         public static void initPool(int connectionCount) {

                   //得到connectionCount個(gè)連接,并把連接加入到連接池中

                   for (int i = 0; i < connectionCount; i++) {

                            connectionPool.put(dbConn.getConnection(fileName),System.currentTimeMillis());//添加進(jìn)來(lái)的連接都沒(méi)有使用過(guò)。

                   }

         }

        

         public Connection getConnection(){

                   Connection conn = null;

                  

                   //如果connectionPool為空,說(shuō)明連接池中沒(méi)有連接,要向連接池中添加一個(gè)連接

                   if(connectionPool.isEmpty()){

                            connectionPool.put(dbConn.getConnection(fileName),System.currentTimeMillis());

                   }

                  

                   //從連接池中獲取一個(gè)連接,獲取的時(shí)候,也獲取時(shí)間,保存到另一個(gè)連接池中

                   Entry<Connection, Long> en =connectionPool.entrySet().iterator().next();

                   conn = en.getKey();//獲取一個(gè)connection對(duì)象。

                   connectionPool.remove(conn);//移除con對(duì)象

                  

                   return conn;

         }

        

         /*

          * 設(shè)置一個(gè)定時(shí)器

          *   每隔一個(gè)小時(shí)監(jiān)測(cè)一下connectionpool連接池中的連接個(gè)數(shù)

          *   如果個(gè)數(shù)過(guò)少,創(chuàng)建新連接,如果個(gè)數(shù)過(guò)多,則移除連接.

          *   還要保證連接是持續(xù)的,保證每8小時(shí)執(zhí)行一次sql語(yǔ)句

          */

         public static void timer(){

                   Timer timer = new Timer();

                  

                   timer.scheduleAtFixedRate(new TimerTask() {

                            //指定時(shí)間要執(zhí)行的代碼

                            @Override

                            public void run() {

                                     int size =connectionPool.size();

                                     /**

                                      * 對(duì)連接池的連接進(jìn)行檢驗(yàn),小于20個(gè),則說(shuō)明連接池的數(shù)量過(guò)少,需要向里面添加新連接至20個(gè)。

                                      * 但是正在使用的連接可能還會(huì)歸還,所以以后還可能多出來(lái)連接。所以還要檢驗(yàn)連接數(shù)量是否多余20個(gè)。

                                      */

                                     if(size < 20){

                                               for (; size < 21;size++) {

                                                        connectionPool.put(dbConn.getConnection(fileName),System.currentTimeMillis());

                                               }

                                     }

                                    

                                     /**

                                      * 因?yàn)闄z測(cè)到連接小于20個(gè)時(shí),可能有些連接正在使用,會(huì)添加連接至20個(gè)。

                                      * 當(dāng)正在使用的連接已經(jīng)使用完了,會(huì)歸還給連接池,這是連接池的數(shù)量會(huì)多于20個(gè),所以要?jiǎng)h除多余的連接,這樣保證連接的數(shù)量動(dòng)態(tài)平衡。

                                      * 移除時(shí)盡量移除長(zhǎng)時(shí)間不使用的連接

                                      *

                                      */

                                     if(size > 20){

                                               for (; size < 21;size--) {

//                                                     Entry<Connection,Long> en = connectionPool.entrySet().iterator().next();

                                                        connectionPool.remove(0);//移除con對(duì)象

                                               }

                                     }

                                    

                                     //鏈接8小時(shí)后就會(huì)關(guān),所以八小時(shí)內(nèi)就要使用一次,而且再次執(zhí)行會(huì)判斷用不用!

                                     /*

                                      * 判斷前連接是否八小時(shí)內(nèi)被執(zhí)行過(guò),

                                      * 如果執(zhí)行過(guò),那么不用管,

                                      * 如果沒(méi)有被執(zhí)行過(guò),那么執(zhí)行一天sql語(yǔ)句,確保連接不會(huì)關(guān)閉。

                                      * 一個(gè)大的連接池,用來(lái)保存總的連接數(shù)。

                                      * 將使用的連接使用時(shí),保存到另一個(gè)連接中

                                      * 但是怎么確保連接的時(shí)間呢?

                                      */

                                     //遍歷這連接池中所有的連接,查看每個(gè)連接用的時(shí)間,如果時(shí)間7個(gè)小時(shí)沒(méi)有用了,那么使用一次

                                     /**

                                      * 每次得到當(dāng)前時(shí)間,計(jì)算出時(shí)間差,超過(guò)7小時(shí)沒(méi)有使用,就使用一次。

                                      */

                                    

                                     /*

                                      * 定義一個(gè)Map集合,用于存放con和是否被修改的變量

                                      * 為什么要不直接把這個(gè)connection重新加入到map中,而要重新定義這個(gè)變量?

                                      * 因?yàn)閙ap集合在遍歷的時(shí)候不能修改集合,否則會(huì)出現(xiàn)異常。

                                      */

                                     Map<Boolean,Connection>conMap = new HashMap<Boolean,Connection>();

 

                                     /*

                                      * for循環(huán)遍歷的時(shí)候不能修改集合元素的內(nèi)容。

                                      */

                                     for (Entry<Connection,Long> en : connectionPool.entrySet()) {

                                               long time =System.currentTimeMillis() - en.getValue();

                                              

                                               Connection con =en.getKey();

                                               if(time >MAX_UNUSED_TIME){

                                                        /**

                                                         * 執(zhí)行一個(gè)sql語(yǔ)句

                                                         */

                                                       

                                                        String sql ="drop table if exists tables";

                                                       

                                                        try {

                                                                 con.prepareStatement(sql).execute();

                                                                

                                                                 conMap.put(true,con);

                                                                

                                                        } catch(SQLException e) {

                                                                 thrownew RuntimeException("run sql fail!");

                                                        }

                                               }

                                              

                                               conMap.put(false,con);

                                     }

                                    

                                     /*

                                      * 遍歷conMap,如果是false那么取得con,再次存入ConnectionPool中

                                      */

                                     for (Entry<Boolean, Connection>en : conMap.entrySet()) {

                                               if(en.getKey()){

                                                        connectionPool.put(en.getValue(),System.currentTimeMillis());

                                               }

                                     }

                            }

                   }, 0, 60 * 1000);

         }

}


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 南靖县| 青州市| 古交市| 龙井市| 长兴县| 乐平市| 樟树市| 花垣县| 永嘉县| 宁蒗| 宜川县| 蓬溪县| 玉环县| 静海县| 江永县| 乡宁县| 岢岚县| 洛宁县| 哈巴河县| 宜章县| 泽普县| 金华市| 扬中市| 肥东县| 颍上县| 江西省| 建湖县| 开原市| 衡水市| 天镇县| 巫山县| 建始县| 宁都县| 和硕县| 年辖:市辖区| 平乡县| 衡南县| 平远县| 张掖市| 双鸭山市| 林州市|