单例模式

201 阅读2分钟

单例模式

饿汉式

构造器私有化

类的内部创建对象

向外暴露一个静态的公共方法

//饿汉式 静态变量
class Singleton {
    //
    private Singleton() {

    }

    private final static Singleton intance = new Singleton();

    public static Singleton getIntance() {
        return intance;
    }

}

可以用 可能造成内存浪费

//饿汉式 静态代码块
class Singleton {
    //构造器私有化
    private Singleton() {
    }

    private static Singleton intance;

    static {
        intance = new Singleton();
    }

    public static Singleton getIntance() {
        return intance;
    }

}

懒汉式

//懒汉式 非线程安全的
class Singleton {
    private static Singleton instance;
    private Singleton(){}

    //当使用到该方法时 才去创建instance
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

这种模式线程不安去

//懒汉式 线程安全 同步方法
class Singleton {
    private static Singleton instance;
    private Singleton(){}

    //当使用到该方法时 才去创建instance
    //加入同步处理代码 解决线程安全问题
    // 每次掉用都同步 效率太低
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

这种模式线程安全 但是每次获取实例都线程同步 效率低

/**
 * 双重检查
 */
class Singleton {
    private static volatile Singleton singleton;
    public static Singleton getInstance() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

双重检查 保证线程安全

会经过三步操作

1.分配内存空间

2.执行构造方法,初始化对象

3.把这个对象指向这个空间

以上的步骤,默认情况是 123 但是,如果出现 132 的情况,恰巧此时A线程占有了,如果此时B线程也要使用的话, 就会直接认为singleton不为空,则会返回singleton,然而此时singleton还没有完成创建, 此时是一片虚无,会导致错误。所以需要在singleton前面加 volatile 。

/**
 * 静态内部类 推荐使用
 */
class Singleton {
    private static volatile Singleton singleton;
    //根据jvm类装载机制来保证初始化
    private static class SingletonIntstance{
        private static final Singleton INSTANCE = new Singleton();
    }

    public static synchronized Singleton getInstance() {
        return SingletonIntstance.INSTANCE;
    }
}

public class SingletonTest07 {
}
//枚举
enum Singleton {
    INSTANCE;
}