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关闭才好?
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关闭才好?
是的
preparedstatement和result应该怎么关闭???
finally里关闭,里面在加try,catch
public synchronized static Singleton getInstance()...{
if(instance==null)...{
instance= new Singleton();
}
return instance;
}
如果有2个线程同时调用getInstance方法,2个方法都认为instance==null,这样就有可能创建2个实例,这样就不是单例了
加上synchronized后一个时间只能有一个线程访问这个方法
不错,你的确是关闭了conn,这只能保证你关闭了conn,但是conn对象还是存在的,所以即使你关闭了它,无论何时输出System.out.println(conn1);结果永远都是同一个conn实例。
你可以这样做,关闭它之后再conn=null.
并不是对象“嵌在内存中”,而是jvm检测到你在接下来还会使用到conn(System.out.println(conn1)),所以才没有调用GC释放掉它。其实,只要你以后不再使用conn,完全不必理会它,jvm会在某个时候自动对conn进行垃圾回收的。举一反三,这个道理也适用于socket。
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后一个时间只能有一个线程访问这个方法
多加载器很好理解,就是同时有多个类加载器对Singleton进行加载,这个时候Singleston的Class可能有多个内存副本,这样的话,Singleston类中的static field在内存中也不是唯一的,只是在某个加载器中是唯一的。所以这种情况没有办法保证其在内存中只存在一个instance,只能保证在同一个加载器中只有一个instance。
同时多线程(简称SMT)就是说多个逻辑处理器,每个逻辑处理器都有一套自己的运行结构,这种情况下,应用程序很难保证这几个逻辑处理器间singleton的Class只有一个副本,只能说是在单个逻辑处理器上是单例的。操作系统能否保证各逻辑处理器间singleton的Class只有一个副本,这就不得而知了,估计也很困难!以上是我对“非同时多线程多加载器”这个限定词的理解,我觉得这个限定对我们基于中间件(Servlet之类)开发的应用程序不会有什么影响,因为一般情况下,操作系统将处理器的个数和执行环境透明化了,而中间件又将我们的环境contextloader做了很好的管理,所以基本上就不用考虑这些问题了。当然如果自己要管理应用程序的类加载器,那么就要注意这种“单例”的有效范围了!这是我的理解,有不对的地方,请高手们多板砖
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。
但是到最后发现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关闭数据库的操作
public class Simple {
private static Simple me = new Simple();
private Simple(){
} public static Simple getInstance() {
return me;
}
}
这样在一个类加载器中就只有一个该类的实例2、就一个main线程,当然结果就一样了啊,再起个线程,运行这段代码就看到差别了3、完全没明白你的rs在哪用的,更没明白你写这段代码干什么用的