本人使用了STRUTS框架开发了一个网站,服务器是TOMCAT6.0,数据库是MSSQL2005,JDBC驱动程序是微软的sqljdbc2005最新版。数据库连接是使用TOMCAT的连接池技术。
问题就是使用连接池后,数据库的活动监视器内的“进程信息”有很多进程没有关闭,有时多达几百个,状态都是“睡眠”,为什么这些进程没有关闭的?当这些进程达到一定数目后,网站的速度就变得越来越慢,有时还要重启。但我另一个使用ASP编写的网站,使用数据库直接连接的,用完后即关闭,数据库的活动监视器内的“进程信息”就只有一到两个,速度也很快。是不是我的连接池设置有问题?或者是我的程序编写有问题?很多人会说我每次用完后,没有在finally中close连接,但我每个连接模块都有这样的操作,但为什么还是这样?
现在急需解决这方案的专家,如能解决,可以给予一定的报酬,因为现在网站被我改成JSP后,经常死掉,老板已严重生气,后果很严重,如再不解决,很可能会丢掉工作。恳切各位帮帮忙!
我的QQ是:358778068
谢谢大家帮帮忙!
------解决方案--------------------
- Java code
import java.sql.Connection;import java.sql.SQLException;import javax.naming.Context;import javax.naming.InitialContext;import javax.naming.NamingException;import javax.sql.DataSource;public class ConnectionFactory { private static DataSource ds = null; private ConnectionFactory() { } static { try { Context initCtx = new InitialContext(); Context ctx = (Context) initCtx.lookup("java:comp/env"); ds = (DataSource)ctx.lookup("jdbc/main"); }catch(NamingException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return ds.getConnection(); }}import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;public class JdbcUtil { public static void close(ResultSet rs, Statement st, Connection con) { close(rs); close(st); close(con); } public static void close(ResultSet rs) { if(rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } } /** * PreparedStatement, CallableStatement 都是 Statement 的子类,可以共用这个方法 * @param st */ public static void close(Statement st) { if(st != null) { try { st.close(); } catch (SQLException e) { e.printStackTrace(); } } } public static void close(Connection con) { if(con != null) { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } private JdbcUtil() { }}
------解决方案--------------------
看样子是高并发时候多线程访问关闭连接问题,可以试用threadLocal取con关闭
而且关con可以在过滤器关,你每个方法close下,万一忘记不就资源没关么~
- Java code
public class DBUtil { private static final ThreadLocal threadLocal = new ThreadLocal(); private DBUtil() { } /** * 获取当前数据库连接 * * @return * @throws Exception */ public synchronized static Connection getCurrentConnection() throws Exception { Connection conn = (Connection) threadLocal.get(); try { if (conn == null) { conn = ConnectionProvider.getConnection(); conn.setAutoCommit(false); threadLocal.set(conn); } } catch (Exception e) { e.printStackTrace(); throw new Exception("数据源错误..."); } return conn; } public static void closeConnection() throws Exception { Connection conn = (Connection) threadLocal.get(); if (conn != null && !conn.isClosed()) { conn.close(); } threadLocal.set(null); } /** * 释放数据库连接 * * @param conn * @throws Exception */ public static void closeConnection(Connection conn) throws Exception { try { if (conn != null && !conn.isClosed()) { conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } /** * 释放statement 可以不要每次都try * * @param stmt */ public static void freeStatement(Statement stmt) { if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } } /** * 关闭resultset * * @param rs */ public static void closeResultSet(ResultSet rs) { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } } public static void commit() throws Exception { getCurrentConnection().commit(); } public static void rollback() { try { getCurrentConnection().rollback(); } catch (Exception e) { e.printStackTrace(); } } public static void close(Statement stmt) { if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } } public static void close(ResultSet rs) { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } } public static void close(Connection conn) { try { if (conn != null) { conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } }public class ConnectionProvider { public static DataSource cpds; static { try { Context context = new InitialContext(); cpds = (DataSource) context.lookup("java:comp/env/jdbc/wap"); } catch (NamingException e) { e.printStackTrace(); System.out.println("初始化数据源时出错!"); } } /** * 获取当前的数据库连接, * * @return 返回数据库连接 * @throws Exception * 如果连接配置的数据源错误或者取连接错误则抛出Exception异常 */ public static Connection getConnection() throws Exception { Connection conn = null; if (cpds != null) { conn = cpds.getConnection(); } else { throw new Exception("数据源错误..."); } return conn; }}