读书人

java c/s模式线程JDBC有关问题

发布时间: 2012-08-15 16:57:16 作者: rapoo

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楼所贴的,确实没看出什么问题。

估计要单独测试了。。。



另外,为了安全,考虑应把 pstmt 放到 try 之内,类似:


Connection connection = DB.createConn();
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
pstmt = DB.prepare(connection, sql);//获取stmt
pstmt.setString(1, XXXX);
rs = pstmt.executeQuery();

while(rs.next()){
XXXXXX
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
if (rs!=null) DB.close(rs);
if (pstmt!=null) DB.close(pstmt);
DB.close(connection);
}

[解决办法]
表面上看,没啥问题。楼主把所有关闭里面的cancel方法去了试试。

当然,我倒是有个想法,可以绕开这个问题。

既然是定时有个线程来巡检,不妨把数据库连接,放到TheadLocal里面,每次从这里面取。
要是里面有,并且能用,就直接用;
要是里面有,不能用,就重新放进去一个,用新的这个;
要是没有,就新放进去一个,用新的这个;

当然,线程关闭的时候,释放资源。
[解决办法]
先把方法中所有cancel(); 放在close()前试试

读书人网 >J2SE开发

热点推荐