public class ConnDB {

private static Connection conn = null;

public static  Connection getConn(){
try{
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
conn = DriverManager.getConnectio("jdbc:microsoft:sqlserver://localhost:1433;User=jiayi;password=jiayi456;DatabaseName=jiayi");
}catch(Exception e){
e.printStackTrace();
}
return conn;
}
以上是一个用来获得数据库连接的工具类,下面是一个servletclass a extends HttpServlet{
 public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
ConnDB con=ConnDB.getConn();
..........
利用con做一些处理
...........con.close();
}
}
因为jsp是多线程的,tomcat对每一个请求都会开辟一个线程来处理,所以会同时有多个线程来运行以上那个servlet,会不会出现这种情况:当一个线程获得conn而进行处理的时候,恰好另一个线程把conn给关闭了?
在网上也看了一些资料,对于方法中的局部变量,每个线程都会开辟相应的内存空间来存储,所以以上方法中的conn(局部变量)在被存放在了每个线程的单调内存空间中,所以并不是出现一个线程正在用conn,而另一个把conn给关了,我是这样理解的,不知道对不对。突然又有了点遗憾,connDB中的Connection可是个全局变量啊?这里会不是照成数据的不同步???
做jsp差不多一年了,以前重没注意过数据的同步安全,现在非常后怕!!!
期待高手给讲讲。

解决方案 »

  1.   

    我认为这个是不安全的,原因就在于connDB中的Connection是static的
      

  2.   

    不了解这方面的知识,似乎hibernate也存在类似的问题?不明白~顶!
      

  3.   

    你这个类本身设计得就有问题,你这样实际上是写成了一个不标准的singleton,
    相当于只有一个实例,但实际上却又需要多个实例,确实是非常不安全。去掉static,用正常的实例化类的方式,这样就安全了
      

  4.   

    不一定,如果你的ConnDB 对象是共享的(如单例模式),也不是线程安全的
      

  5.   

    这个。
    如果不用dao框架,都要自己写个简单的dao工厂的。
      

  6.   

    这样肯定存在问题,当一个线程正在使用conn的时候,
    另一个线程调用getConn()方法则会将conn重新实例化一遍.
    可以将你的数据库工具类设计成一个单例模式,getConn()设计成一个非静态方法,将conn设计成这个方法内的局部变量....
    不过最好使用连接池.
      

  7.   

    但是,我感觉我的每一个线程拥有各自的Connection,他们之间并不会相互干扰,所关闭的也是各自的connection,所以线程安全
      

  8.   

    我以前也会有这样的疑问,所以我尽量避免出现这样的错误,第一,如果不是大型的系统,能不用单例就不用单例,保证每个用户一个新的实例。
    如果你要测试servlet是不是多线程的,可以做一个计数器,然后2个页面访问,看看计数器有没有改变,我记得servlet不是线程安全的。
    所以你可以使用c3p0或者jndi的连接池来做,不会出这么多问题。
      

  9.   

    静态方法去conn没什么不好 改成静态从连接池取就好了,如果所有的客户都公用一个conn那么很可能导致网络延迟 等待一些加了锁的查询或是提交
      

  10.   

    我建议你
    去掉static,用正常的实例化类的方式,这样应该安全了
      

  11.   

    我错了,对一个static变量,是被每一个实例所共享的。
      

  12.   

    学习了,我也是做java web的,还真没仔细研究过这些问题
      

  13.   

    java web的初学者,但是我也认为这是不安全的,就像是多线程问题中的同步问题一样,jsp采用多线程来处理各用户的访问,那么有static的话所有用户公用一个,确实很可能出现前辈们说的同步问题,感觉应该去掉static 但是如果每个用户一个实例对象的话,当用户太多的时候会太占用资源吧?
      

  14.   

    对于线程安全问题,建议你用spring去管理对于连接问题,建议你用数据库连接池其实什么东西都不是绝对的,只能在开发中避免,尤其是web项目,总是需要去维护。不要总是顾虑太多,否则你的代码会显得小气。
      

  15.   


    import java.sql.Connection;
    import java.sql.DriverManager;public class ConnDB { static {
    try {
    Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    }
    } public static Connection getConn() {
    Connection conn = null;
    try {
    conn = DriverManager
    .getConnection("jdbc:microsoft:sqlserver://localhost:1433;User=jiayi;password=jiayi456;DatabaseName=jiayi");
    } catch (Exception e) {
    e.printStackTrace();
    }
    return conn;
    }
    }
    以上是线程安全的代码..还有几个地方我需要和您解释下1:Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");加载数据库驱动..在整个应用中.只需要加载一次就可以了..
    而不是说每次得到一个连接都加载一次驱动..所以,我这里在静态代码块(关于这个名词的解释以及静态代码块的作用,您可以通过百度或google搜一下,我这里就不解释了)中加载一次.而通常我在开发项目的做法是.. 有一个伴随tomcat启动而初始化的Servlet, 再他的init方法中加载数据库驱动..这是第一.2:关于您说的线程安全问题.. 您写的代码的确是有线程安全的隐患.. 原因就是在于.. 这个Connection对象是成员变量.. 去除了static会报语法错误.. 因为静态方法.. 不能直接访问类属性.. 依然能在一个方法中获得这个Connection.. 为什么要使用成员变量呢..??这是我的想法..如果哪里说错了. 请各位大侠指出.. 一起交流交流思想..
      

  16.   

    我觉得使用连接池就可以解决问题了啊,当servlet需要连接数据库的时候就从连接池中取出一个connection。而如果有另外的servlet也需要连接数据库,那连接池就给他返回另外一个connection对象。各自关闭各自的connection,不会造成冲突了啊