日期:2014-05-20  浏览次数:20957 次

java c/s模式线程JDBC问题
最近在做java的c/s应用,用到了JDBC,由于是客户端程序没有使用线程池,而是使用直连方式。程序中有一个线程在一直读取数据库(死循环,每秒种读取一次数据库),但是程序运行半个小时左右就会虚拟机溢出,进行测试发现connection没有关闭,PreparedStatement对象也没有关闭。
 很奇怪我尝试过使用常开connection连接,就是一个操作中保持一个Connection不关闭,但是PreparedStatement的数量也一直在增加,不知道为什么,还是我的程序有问题,附上代码:
数据库操作封装类:
Java code

/**
     * 获取数据库连接
     * @return 数据库连接
     */
    public static Connection createConn() {
        Connection conn = null;
        try {
            Class.forName(DBData.DRIVER);
            conn = DriverManager.getConnection(DBData.getURLForMySQL(), DBData.USER, DBData.PASSWORD);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
            //JOptionPane.showMessageDialog(Source.getMainWindow(), "创建数据库连接失败,请检查服务器运行状态.");
            //return createConn();
        }
        
        return conn;
    }
    
    /**
     * 获取数据库Statement
     * @param conn 数据库连接
     * @return 数据库stmt
     */
    public static Statement createStmt(Connection conn) {
        Statement stmt = null;
        try {
            stmt = conn.createStatement();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return stmt;
    }
    
    /**
     * 获取数据库PreparedStatement
     * @param conn 连接
     * @param sql sql语句
     * @return PreparedStatement
     */
    public static PreparedStatement prepare(Connection conn, String sql) {
        PreparedStatement ps = null;
        try {
            ps = conn.prepareStatement(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return ps;
    }
    
    /**
     * 关闭Connection
     * @param conn 数据库连接
     */
    public static void close(Connection conn) {
        try {
            conn.close();
            conn = null;
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 关闭Statement
     * @param stmt Statement
     */
    public static void close(Statement stmt) {
        try {
            stmt.close();
            stmt.cancel();
            stmt = null;
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 关闭PreparedStatement
     * @param pstmt PreparedStatement
     */
    public static void close(PreparedStatement pstmt) {
        try {
            pstmt.close();
            pstmt.cancel();
            pstmt = null;
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 关闭结果集
     * @param rs 查询结果集
     */
    public static void close(ResultSet rs) {
        try {
            rs.close();
            rs = null;
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }


使用之后每次都会
Java code

    Connection connection = DB.createConn();
        PreparedStatement pstmt = DB.prepare(connection, sql);//获取stmt
        ResultSet rs = null;
        try {
            pstmt.setString(1, XXXX);
            rs = pstmt.executeQuery();
            
            while(rs.next()){
                XXXXXX
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            DB.close(rs);
            DB.close(pstmt);
            DB.close(connection);
        }



附上测试截图


这里测试数据connection都已经有了3万个,而我都是每次打开都关闭了为什么会这样,而且程序跑一会就会虚拟机溢出。各位大侠,小弟在此谢过,附上100分

------解决方案--------------------
上面的代码看不出问题,代码上看执行后会关闭,但执行后是否真正关闭了呢?其次将刷新的频率调低,看相等的时间内比较创建的连接数,如果差别比较大,可能是刷新导致创建连接而无法关闭。
我也不知道对不对,只是说出自己的想法,有不对的地方,请大家谅解。
------解决方案--------------------
你9楼所贴的,确实没看出什么问题。

估计要单独测试了。。。