首页 > 学院 > 开发设计 > 正文

连接池链接超时

2019-11-08 20:40:43
字体:
来源:转载
供稿:网友

数据库连接池中的connection在八小时内没有被用到,则会自动断开连接,那么怎么处理数据库连接超时的问题?

         我在自己写mybatis框架的时候,这样处理的:首先确保连接池中有指定数量的链接:将connection和创建时间System.currentTimeMillis()以键值对的形式存放在map集合中,用一个定时器,每隔1小时检查一下连接数目,数目大于指定个数,则从map中移除,小于指定个数,则加入新的链接。其次:检查连接在7个小时内是否被用,如果没有被用,则执行一个sql语句:String sql = "drop table if exists tables";将connection对象重新加入到map集合中。

我的代码:

public class ConnectionFacory{

         PRivate static ConnectionFacory instance;

         private static DBConn dbConn = new DBConn();//获取链接的类

         private static String fileName = null;//数据库的文件名,先为null,初始化对象后改为传入的值

        

         /**

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

          * 如果用Map<Connection,time>的数据类型去保存

          * time为初始化连接的毫秒值,没有使用过的话设置为0.

          * 从数据库获取时,设置获取当前的时间毫秒值。

          * 并把这个连接加入到另一个连接池中

          *

          */

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

        

         /**

          * 设置最大时间为一个常量

          */

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

        

         /**

          * 使用的连接都加入到这个连接池中

          */

         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;//属于共享数据

                            initPool(20);

                            timer();

                   }

                  

                   return instance;

         }

 

         public static void initPool(int connectionCount) {

                   //得到connectionCount个连接,并把连接加入到连接池中

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

                            connectionPool.put(dbConn.getConnection(fileName),System.currentTimeMillis());//添加进来的连接都没有使用过。

                   }

         }

        

         public Connection getConnection(){

                   Connection conn = null;

                  

                   //如果connectionPool为空,说明连接池中没有连接,要向连接池中添加一个连接

                   if(connectionPool.isEmpty()){

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

                   }

                  

                   //从连接池中获取一个连接,获取的时候,也获取时间,保存到另一个连接池中

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

                   conn = en.getKey();//获取一个connection对象。

                   connectionPool.remove(conn);//移除con对象

                  

                   return conn;

         }

        

         /*

          * 设置一个定时器

          *   每隔一个小时监测一下connectionpool连接池中的连接个数

          *   如果个数过少,创建新连接,如果个数过多,则移除连接.

          *   还要保证连接是持续的,保证每8小时执行一次sql语句

          */

         public static void timer(){

                   Timer timer = new Timer();

                  

                   timer.scheduleAtFixedRate(new TimerTask() {

                            //指定时间要执行的代码

                            @Override

                            public void run() {

                                     int size =connectionPool.size();

                                     /**

                                      * 对连接池的连接进行检验,小于20个,则说明连接池的数量过少,需要向里面添加新连接至20个。

                                      * 但是正在使用的连接可能还会归还,所以以后还可能多出来连接。所以还要检验连接数量是否多余20个。

                                      */

                                     if(size < 20){

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

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

                                               }

                                     }

                                    

                                     /**

                                      * 因为检测到连接小于20个时,可能有些连接正在使用,会添加连接至20个。

                                      * 当正在使用的连接已经使用完了,会归还给连接池,这是连接池的数量会多于20个,所以要删除多余的连接,这样保证连接的数量动态平衡。

                                      * 移除时尽量移除长时间不使用的连接

                                      *

                                      */

                                     if(size > 20){

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

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

                                                        connectionPool.remove(0);//移除con对象

                                               }

                                     }

                                    

                                     //链接8小时后就会关,所以八小时内就要使用一次,而且再次执行会判断用不用!

                                     /*

                                      * 判断前连接是否八小时内被执行过,

                                      * 如果执行过,那么不用管,

                                      * 如果没有被执行过,那么执行一天sql语句,确保连接不会关闭。

                                      * 一个大的连接池,用来保存总的连接数。

                                      * 将使用的连接使用时,保存到另一个连接中

                                      * 但是怎么确保连接的时间呢?

                                      */

                                     //遍历这连接池中所有的连接,查看每个连接用的时间,如果时间7个小时没有用了,那么使用一次

                                     /**

                                      * 每次得到当前时间,计算出时间差,超过7小时没有使用,就使用一次。

                                      */

                                    

                                     /*

                                      * 定义一个Map集合,用于存放con和是否被修改的变量

                                      * 为什么要不直接把这个connection重新加入到map中,而要重新定义这个变量?

                                      * 因为map集合在遍历的时候不能修改集合,否则会出现异常。

                                      */

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

 

                                     /*

                                      * for循环遍历的时候不能修改集合元素的内容。

                                      */

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

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

                                              

                                               Connection con =en.getKey();

                                               if(time >MAX_UNUSED_TIME){

                                                        /**

                                                         * 执行一个sql语句

                                                         */

                                                       

                                                        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);

         }

}


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表