1.public class Singleton...{
    private static Singleton instance;
    //私有化构造方法来防止外部通过new 来创建该类的实例
    private  Singleton ()...{       
    }    
    //使用 synchronzied 保证线程安全
    public synchronized static Singleton getInstance()...{
        if(instance==null)...{
            instance= new Singleton();
        }
        return instance;
    }  
}1,单例类的实现. 可以保证在非同时多线程多类加载器的环境下的单例
以上是看到的一篇文章的题目
我都问题是:为什么是非同时多线程多类加载器既然是非同时,那就不是多线程的性质了,好像加了也白加,最多是保证new一个instance的时候多条线程之间不会冲突而已,并且多个线程共用一个instance的话,早晚出问题,如果我解释的有问题,请高手纠正我的想法2 public static void main(String[] args) {
Connection conn1 = ConnectionFactory.getConnection();
// Connection conn2 = ConnectionFactory.getConnection();
System.out.println(conn1);
try {
ConnectionFactory.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}问题:
ConnectionFactory是单例
然后我一直在main里面运行这个
不管运行几次输出结果(System.out.println(conn1);)都一样?
难道对象嵌在内存中啦?3
public class ConnectionFactory {
private static String sql = "";
// private static Connection conn = null;
private static final ThreadLocal<Connection> session = new ThreadLocal<Connection>();
private static PreparedStatement pstmt = null;
private static ResultSet rs = null;
private static Statement stmt = null; private ConnectionFactory() { } public static Connection getConnection() {
Connection conn = session.get();
if (conn == null) {
conn = createConnection();
}
return conn;
} public static Connection createConnection() {
Connection conn = null;
try {
Class.forName("org.gjt.mm.mysql.Driver");
conn = DriverManager
.getConnection(
"jdbc:mysql://******:3306/newData?characterEncoding=UTF-8",
"a", "b");// 114.80.213.11
 
conn.setAutoCommit(false);
session.set(conn);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.err.println("......Create connection error");
}
return conn;
} public static void close() throws SQLException {
Connection conn = session.get();
session.set(null);
if (conn != null) {
conn.close();
}
} public static void close(ResultSet rs, Statement stmt, Connection conn) {
try {
if (rs != null)
rs.close();
if (stmt != null)
stmt.close();
if (conn != null)
conn.close();
} catch (Exception e) {
}
}}问题:
我这个ConnectionFactory应该是单例吧?
那我关闭这个conn的时候
preparedstatement和result应该怎么关闭???
因为上面2个是类的属性,而conn为每个线程类的单独属性
那我应该怎么实现rs,stmt,conn关闭才好?
 

解决方案 »

  1.   

    我这个ConnectionFactory应该是单例吧? 
    是的
    preparedstatement和result应该怎么关闭??? 
    finally里关闭,里面在加try,catch
      

  2.   

    为什么是非同时多线程多类加载器 
    public synchronized static Singleton getInstance()...{
            if(instance==null)...{
                instance= new Singleton();
            }
            return instance;
    }  
    如果有2个线程同时调用getInstance方法,2个方法都认为instance==null,这样就有可能创建2个实例,这样就不是单例了
    加上synchronized后一个时间只能有一个线程访问这个方法
      

  3.   

    问题2:
    不错,你的确是关闭了conn,这只能保证你关闭了conn,但是conn对象还是存在的,所以即使你关闭了它,无论何时输出System.out.println(conn1);结果永远都是同一个conn实例。
    你可以这样做,关闭它之后再conn=null.
    并不是对象“嵌在内存中”,而是jvm检测到你在接下来还会使用到conn(System.out.println(conn1)),所以才没有调用GC释放掉它。其实,只要你以后不再使用conn,完全不必理会它,jvm会在某个时候自动对conn进行垃圾回收的。举一反三,这个道理也适用于socket。
      

  4.   

    preparedstatement和result应该怎么关闭??? 
    try catch里面关闭

    finally{
    Conn.closeRs(rs);
    Conn.closeStm(stm);
    Conn.closeCon(con);
    }
    为什么是非同时多线程多类加载器 
    public synchronized static Singleton getInstance()...{ 
            if(instance==null)...{ 
                instance= new Singleton(); 
            } 
            return instance; 
    }  
    如果有2个线程同时调用getInstance方法,2个方法都认为instance==null,这样就有可能创建2个实例,这样就不是单例了 
    加上synchronized后一个时间只能有一个线程访问这个方法 
      

  5.   

    非同时多线程多加载器
    多加载器很好理解,就是同时有多个类加载器对Singleton进行加载,这个时候Singleston的Class可能有多个内存副本,这样的话,Singleston类中的static field在内存中也不是唯一的,只是在某个加载器中是唯一的。所以这种情况没有办法保证其在内存中只存在一个instance,只能保证在同一个加载器中只有一个instance。
    同时多线程(简称SMT)就是说多个逻辑处理器,每个逻辑处理器都有一套自己的运行结构,这种情况下,应用程序很难保证这几个逻辑处理器间singleton的Class只有一个副本,只能说是在单个逻辑处理器上是单例的。操作系统能否保证各逻辑处理器间singleton的Class只有一个副本,这就不得而知了,估计也很困难!以上是我对“非同时多线程多加载器”这个限定词的理解,我觉得这个限定对我们基于中间件(Servlet之类)开发的应用程序不会有什么影响,因为一般情况下,操作系统将处理器的个数和执行环境透明化了,而中间件又将我们的环境contextloader做了很好的管理,所以基本上就不用考虑这些问题了。当然如果自己要管理应用程序的类加载器,那么就要注意这种“单例”的有效范围了!这是我的理解,有不对的地方,请高手们多板砖
      

  6.   

    问题: 
    ConnectionFactory是单例 
    然后我一直在main里面运行这个 
    不管运行几次输出结果(System.out.println(conn1);)都一样? 
    难道对象嵌在内存中啦? public static Connection getConnection() {
            Connection conn = session.get();
            if (conn == null) {
                conn = createConnection();
            }
            return conn;
        }因为ThreadLocal变量,这个是和当前的线程中相关的,每运行一次,则CurrentThread线程就不一样了,所以get()返回的为空,这样就会重新create一个connection。
    用ThreadLocal能为每个线程有各自的一个connection而不是公用同一个connection。
      

  7.   

    我的那个ConnectionFactory的conn用到了ThreadLocal类
    但是到最后发现conn可以关闭代码如下,但是对应的pstmt和rs不好关闭了    public static void close() throws SQLException {
            Connection conn = session.get();
            session.set(null);
            if (conn != null) {
                conn.close();
            }
        }
    因为conn是和线程有关系的,而pstmt和rs和类有关系
    我应该怎么修改上面的关闭方法???
    难道只能用rs.close,pstmt.close,conn.close关闭数据库的操作
      

  8.   

    第一点太拗口了,单例可以这样写
    public class Simple {
    private static Simple me = new Simple();

    private Simple(){

    } public static Simple getInstance() {
    return me;
    }
    }
    这样在一个类加载器中就只有一个该类的实例2、就一个main线程,当然结果就一样了啊,再起个线程,运行这段代码就看到差别了3、完全没明白你的rs在哪用的,更没明白你写这段代码干什么用的