单例模式的一些认识

private AAA(){
}

1 饿汉式 (线程安全,不能延迟实例化,浪费内存空间)

private static AAA aaa = new AAA();
public static AAA getInstance(){
    return aaa;
}

2 懒汉式 (线程安全,延迟实例化)

private static AAA instance;
public static synchronized AAA getInstance(){

    if(instance==null){
        instance = new AAA();
    }
    return instance;
}

3 Double Check Lock(双重锁机制,线程安全,延迟实例化,效率高)

private static volatile AAA instance;
public static AAA getInstance(){

    if(instance == null){
        synchronized (AAA.class){
            if (instance ==null){
                instance = new AAA();
            }
        }
    }
    return instance;
}

关于此方式中的volatile作用

(1)禁止指令重排序

主要是因为

instance = new AAA();不是一个原子操作

下面这个链接清楚的解释了指令重排序的问题。

https://www.jianshu.com/p/1c72a061b40e

(2)保证可见性

线程A在自己工作线程中创建了实例,但还未同步到主存中,线程B判断主存中instance还是null,那么线程B又将在自己工作线程中创建一个实例,这样就会创建多个实例。

 

4 静态内部类(线程安全,延迟实例化,效率高)

private static class BBB{
    private static final AAA aaa = new AAA();
}

public static AAA getInstance(){
    return BBB.aaa;
}

静态内部类的加载方式:

内部静态类不会自动初始化,只有调用静态内部类的方法,静态域,或者构造方法的时候才会加载静态内部类。

 

5、枚举(线程安全,调用效率高,不能延时加载,可以天然的防止反射和反序列化调用)

举个栗子:一旦你实现了serializable接口,他们就不再是单例的了,因为readObject()方法总是返回一个 新的实例对象,就像java中的构造器一样。

public enum BBC {

    //枚举元素本身就是单例
    INSTANCE;
    
    private BBC() {
    
    }
    
    //添加自己需要的操作
    public void singletonOperation(){
    }
}
    /**
      * 使用方法
      */
    boolean bl = BBC.INSTANCE.singletonOperation();

枚举完成的单例有一下几个优点: 
1,线程安全 
2,自由序列化 
3,即使使用反射机制也无法多次实例化一个枚举量

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章