标签:
顾名思义,就是保证在JVM中只有实例对象存在3、某些情况下,需要一个类来控制全局时,就需要单例。(一个国家只能有一个最高领导人,多了话,听谁的?)
一个简单的懒汉式:
public class Single {
private static Single s = null;//私有静态实例,防止被外部引用,初始null,延迟加载
private Single(){}
//返回实例
public static Single getInstace(){
if(s==null)
s = new Single();
return s;
}
//如果对象需要被用于序列化,这样就可以对象在序列化前后保持一致
public Object readResolve(){
return s;
}
}<span style="white-space:pre"> </span>public class Single {
private static Single s = null;
private Single(){}
public synchronized static Single getInstace(){
if(s==null)
s = new Single();
return s;
}
public Object readResolve(){
return s;
}
}
public static Single getInstace(){
if(s==null){ //解决效率
synchronized(Single.class){
if(s == null) //解决安全问题
s = new Single();
}
}
return s;
}
将 synchronized 加在了内部,也就是说当调用的时候是不需要加锁的,只有在 s 为 null, 并创建对象的时候才需要加锁, 性能有一定的提升。
貌似解决了问题,但是有可能出现隐患。
在 Java 指令中创建对象和赋值操作是分开进行的,也就是说s = new Single();语句是分两步执行的。
但是JVM却不是保证两者的顺序,有可能JVM先分配空间,再赋值给s,然后在初始化Single实例,这样就会出现问题
比如:A , B 两个线程
1.A,B同时通过第一个if判断,进入
2.A线程先获得锁对象,s == null , 执行s = new Single();
3.但是,JVM线程分配Single实例的空白内存,并赋值s,但是还有初始化s,A线程就离开synchronized
4.B线程拿到锁对象,但是此时的s!=null,所以B线程离开
5.那么调用getInstace()的程序,因为没有初始化,出现问题
所以:多线程环境下,懒汉式的隐患很难根除,所以开发一般不会用,采用用饿汉式
(面试肯定是问懒汉式,技术含量高)
饿汉式
public class Single {
private static final Single s = new Single();
public static Single getInstance(){
return Single.s;
}
}public class Single {
private Single(){}
public static class SingleChild{
private static Single s = new Single();
}
public static Single getInstance(){
return SingleChild.s;
}
public Object ReadResolve(){
return getInstance();
}
}
标签:
原文地址:http://blog.csdn.net/wjw0130/article/details/42089145