单例模式是设计模式中常用的一种模式
在多线程中,单例模式需要保证发布对象的唯一性,因此有三种方案来保证安全发布对象
1.懒汉模式,
在双重同步锁下获取实例,来保证对象唯一,但是因为jvm指令重排,所以是不能保证对象唯一的
@NotThreadSafe
public class SingletonExample4 {
private SingletonExample4(){}
private static SingletonExample4instance =null;
//1.memory = allocate() 分配对象内存空间
//2.ctorinstance() 初始化对象
//3.instance = memory 设置instance指向刚分配的内存
//jvm和cpu优化,发生指令重排
//1.memory = allocate() 分配对象内存空间
//3.instance = memory 设置instance指向刚分配的内存
//2.ctorinstance() 初始化对象
//静态的工厂方法,
public static synchronized SingletonExample4 getInstance(){
if(instance ==null){//双重检测
synchronized(SingletonExample4.class){//同步锁
if(instance ==null){
instance =new SingletonExample4();
}
}
}
return instance;
}
}
因此,需要加入volatile关键字,来保证jvm不会发生指令重排
private volatile static SingletonExample5instance =null;
2.饿汉模式
饿汉模式通常能够保证对象唯一,但是需要考虑对象的使用频率,如果使用频率不高,则不推荐,浪费性能
@ThreadSafe
public class SingletonExample6 {
private SingletonExample6(){}
private static SingletonExample6instance =null;
static {
instance =new SingletonExample6();
}
//静态的工厂方法,
public static synchronized SingletonExample6 getInstance(){
return instance;
}
public static void main(String[] args) {
System.out.println(getInstance().hashCode());
System.out.println(getInstance().hashCode());
}
}
3.枚举模式
通过内部枚举类来保证jvm只会初始化一次
@ThreadSafe
public class SingletonExample7 {
private SingletonExample7(){
}
public static SingletonExample7 getInstance(){
return Singleton.INSTANCE.getSingleton();
}
private enum Singleton{
INSTANCE;
private SingletonExample7singleton;
//JVM保证这个方法只被调用一次
Singleton(){
singleton =new SingletonExample7();
}
public SingletonExample7 getSingleton() {
return singleton;
}
}
}
网友评论