您的位置:首页 > 编程语言

两种比较“强壮”的单例代码。

2015-08-08 21:14 477 查看

第一种:

public class SingletonClass{
private static SingletonClass instance = null;
public static SingletonClass getInstance(){
if(instance == null){
synchronized(SingletonClass.class){
if(instance == null){
instance = new SingletonClass();
}
}
}
return instance;
}
private SingletonClass(){

}
}


此种方法采用了将构造方法改为“private”来修饰,这样就使得用户无法通过用new的方式来获得这个类的实例,但此类提供了一个供外部获得唯一实例的static方法getInstance(),当getInstance()方法第一次被调用时instance这个属性一定是为空的,当instance为空的时候要new一个实例出来,new出的这个实例也是程序运行过程中唯一的实例。

<span style="white-space:pre">	</span>if(instance == null){
synchronized(SingletonClass.class){
if(instance == null){
instance = new SingletonClass();
}
}
}
return instance;


这是getInstance()方法中的全部代码,我们先看synchronized(){}这段,为什么这是一个“强壮”的单例呢,就是因为下面这条语句synchronized(){},如果不加synchronized(){}的话如果有多线程同时来调用getInstance()方法,就会可能就会导致单例模式的失效,出现多个实例。例如:A和B先后调用getInstance(),A线程第一次调用getInstance()方法时判断if为空,程序将会向下执行new实例的代码,不用多想一定会new一个实例,但当A想往下执行new一个新实例时CPU将控制交给了B线程,B在执行if语句时也判断为空,也不用多想,它执行了下面语句new出一个实例,些时CPU又回到A线程执行下面创建实例的代码,这时就出现了单例类矛盾的出现了两个实例。

所以,使用synchronized(){}代码是将判断instance是否为空和为空之后new实例的的代码在被多个线程调用的过程中只能有一个线程执行。大家会看到为什么要有两个if(instance == null)的判断呢,这是因为如果没有最外面的if判断时每次调用getInstance()方法时都会执行synchronized(){}代码,但每次执行synchronized(){}代码会比较慢,

所以考虑到性能的原因最外面先判断instance是否为空在决定是否执行synchronized(){}代码。

第二种:

public class SingletonClass {

private static class SingletonClassInstance {
private static final SingletonClass instance = new SingletonClass();
}

public static SingletonClass getInstance() {
return SingletonClassInstance.instance;
}

private SingletonClass() { }
}


第二程实现的单例的方法使用了static的内部类,getInstance()方法返回的是内部类中instance属性,内部类内的instance属性用static final修饰,不管调用getInstance()方法被调用多少次,或被多个线程同时调用,都只会有一个实例存在。第二种方法比较推荐,只是使用了简单的内部类。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: