单例模式

单例模式用于确保一个类只有一个实例,并且提供一个静态的全局访问点。

下面介绍了懒汉式和饿汉式单例模式的实现方式,通过私有化构造器来防止通过外部创建实例,因此单例类必须自己创建自己的唯一实例。

线程安全的饿汉式单例模式实现:

饿汉式在类装载的时候直接初始化实例对象,提供静态的访问方法getInstance

public class Singleton {
    private static Singleton instance = new Singleton();

    private Singleton(){}

    public static Singleton getInstance(){
        return instance;
    }
}

线程不安全的懒汉式单例模式实现:

构造器私有化,但是内部创建对象只有在第一次调用getInstance才开始,但是,多个线程调用该方法时,有可能返回多个对象

class ClassName{

    private static ClassName instance;

    private ClassName(){}

    public static getInstance(){
        if(instance==null){
            instance = new Classname();
        }
        return instance;
    }
}

线程安全的懒汉式单例模式&双重检查:

区别于线程不安全的方法,这里通过双重检查的方式确保安全地创建实例,同时Synchronized不会对性能造成太大的影响。volatile关键字禁止了指令重排序,使得 instance 一但修改,立即刷到主存,其他线程立即可见。但是volatile同时蔽掉虚拟机中一些必要的代码优化

第一次检查,使得同步代码块不是每次都要执行,优化函数执行效率,第二次用于保证实例只创建一次

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

通过静态内部类实现的线程安全单例模式

当getInstance方法第一次被调用的时候,静态内部类得到初始化,从而创建Singleton的实例,由于是静态的域,因此只会在虚拟机装载类的时候初始化一次,并由虚拟机来保证它的线程安全性。

这个模式的优势在于,getInstance方法并没有被同步,因此延迟初始化并没有增加任何访问成本。

class ClassName{
    private ClassName(){}
   
    private static class SingleClassName{
        private static final ClassName instance = new ClassName();
    }
    
    public static ClassName getinstance(){
        return SingleClassName.instance;
    }
}

通过枚举实现线程安全的全局唯一的单例模式

但是考虑到类的反射机制,通过私有构造器无法确保一个类只有一个实例。所以通过枚举实现的单例更加安全。

public enum  EnumSingleton {
    INSTANCE;
    public EnumSingleton getInstance(){
        return INSTANCE;
    }
}
 posted on 2020-10-25 17:17  春秋流千事  阅读(71)  评论(0)    收藏  举报