单例模式 JAVA

时间:2024-04-07 12:22:48
单例模式

什么是单例模式?

  • 1、单例类只能有一个实例。
  • 2、单例类必须自己创建自己的唯一实例。
  • 3、单例类必须给所有其他对象提供这一实例。

应用:数据库的连接类,这样就可以确保只创建一次。节省资源。

单例模式代码:涉及懒加载、双重检查锁、volatile防止指令重排。

懒加载:在调用方法的时候才初始化对象。对应的是饿汉模式:private static Singleton singleton=new Singleton();

双检锁: 第一个是指synchronized(Singleton.class){…} 之所以将锁加在这里而不是方法上是因为加在方法上的话,多个线程调用这个方法都要抢锁,而实际上我们只需要保证创建对象时线程安全即可。所以为了更细粒度的锁我们加在了判空前。

第二个是指锁内还写了一个判空条件。这是因为线程A和B都进入了第一个判空条件内,然后这时候A加了锁,开始创建创建对象。结束后B线程也会创建对象。所以就需要再加一个判空条件。

volatile: singleton=new Singleton();其实分为三步:1.给Singleton分配空间。2.初始化对象(调用Singleton的构造方法)3.将singleton这个引用指向刚分配的内存地址。

但如果指令重排按照1,3,2的顺序进行。如果2还没有执行完,这时再来一个线程B发现singleton不为空了,直接return singleton,而我们的构造方法还没执行呢!这时就会出错。

class SingletonLazy {
    // 使用private防止其他类使用
    // 使用双重检查锁 必须加上volatile 防止指令重排
    private volatile static SingletonLazy singletonLazy;
    // 私有化构造器
    private SingletonLazy() {};

    public  static SingletonLazy getInstance() {
        // 双重检查锁
        if (singletonLazy == null) {
            synchronized (SingletonLazy.class) {
                //双重检查锁
                if (singletonLazy == null) {
                    singletonLazy = new SingletonLazy();
                }
            }
        }
        return singletonLazy;
    }
}