单例模式的优雅解决

单例模式经常会听到的常用创建是饿汉模式和懒汉模式,今天在学习单例模式时借鉴了一些大佬的文章,记录下

1.饿汉模式

package com.bigbear.chapter012_singleton;

/**
 * @author: yxb
 * @date: 2022/10/18 21:59
 * @version: v1.1
 * @description: 单例-饿汉模式
 * 优点:对象提前创建好了,使用的时候无需等待,效率高
 * 缺点:对象提前创建,所以会占据一定的内存,内存占用大,以空间换时间
 */
public class Singleton_1 {
    private final static Singleton_1 instance = new Singleton_1();

    public static Singleton_1 getInstance() {
        return instance;
    }


}

2.懒汉模式

package com.bigbear.chapter012_singleton;

/**
 * @author: yxb
 * @date: 2022/10/18 22:08
 * @version: v1.1
 * @description: 懒汉模式
 */
public class Singleton_2 {
    private static Singleton_2 instance;

    private Singleton_2() {

    }

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

3.double-check

package com.bigbear.chapter012_singleton;

/**
 * @author: yxb
 * @date: 2022/10/18 22:15
 * @version: v1.1
 * @description: double-check
 * 双重检查锁定的问题是:并不能保证它会在单处理器或多处理器计算机上顺利运行。
 *
 * 双重检查锁定失败的问题并不归咎于 JVM 中的实现 bug,而是归咎于 Java 平台内存模型。内存模型允许所谓的“无序写入”,这也是这些习语失败的一个主要原因。
 *
 *
 * singleton = new Singleton();
 * 该语句非原子操作,实际是三个步骤。
 *
 * 1.给 Singleton 分配内存;
 * 2.调用 Singleton 的构造函数来初始化成员变量;
 * 3.将给 singleton 对象指向分配的内存空间(此时 singleton 才不为 null );
 * 虚拟机的指令重排序–>
 *
 * 执行命令时虚拟机可能会对以上3个步骤交换位置 最后可能是132这种 分配内存并修改指针后未初始化 多线程获取时可能会出现问题。
 *
 * 当线程A进入同步方法执行singleton = new Singleton();代码时,恰好这三个步骤重排序后为1 3 2,
 *
 * 那么步骤3执行后 singleton 已经不为 null ,但是未执行步骤2,singleton对象初始化不完全,此时线程B执行 getInstance() 方法,
 * 第一步判断时 singleton 不为null,则直接将未完全初始化的singleton对象返回了。
 *
 * 解决
 * 如果一个字段被声明成volatile,Java线程内存模型确保所有线程看到这个变量的值是一致的,同时还会禁止指令重排序
 *
 * 所以使用volatile关键字会禁止指令重排序,可以避免这种问题。使用volatile关键字后使得 singleton = new Singleton();
 * 语句一定会按照上面拆分的步骤123来执行。
 *
 * 另一个问题
 * 单例模式并不是绝对安全的,可以通过反射来破坏,只有枚举安全类是安全的。
 */
public class Singleton_3 {
    private static Singleton_3 instance;

    private Singleton_3() {

    }

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

4.double-check + volatile

package com.bigbear.chapter012_singleton;

/**
 * @author: yxb
 * @date: 2022/10/18 22:15
 * @version: v1.1
 * @description: double-check  volatile
 */
public class Singleton_4 {
    private static volatile Singleton_4 instance;

    private Singleton_4() {

    }

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

5.枚举方式(Effective In Java推荐的方式)

package com.bigbear.chapter012_singleton;

/**
 * @author: yxb
 * @date: 2022/10/18 22:15
 * @version: v1.1
 * @description: 
 */
public class Singleton_5 {

    private Singleton_5() {

    }

    private static class InstanceHolder {
        private final static Singleton_5 instance = new Singleton_5();
    }

    public static Singleton_5 getInstance() {
        return InstanceHolder.instance;
    }
}
package com.bigbear.chapter012_singleton;

/**
 * @author: yxb
 * @date: 2022/10/18 22:15
 * @version: v1.1
 * @description:
 */
public class Singleton_6 {

    private Singleton_6() {

    }

    private enum Singleton {
        INSTANCE;
        private final Singleton_6 instance;
        Singleton() {
            instance = new Singleton_6();
        }
        public Singleton_6 getInstance() {
            return instance;
        }
    }

    public Singleton_6 getInstance() {
        return Singleton.INSTANCE.getInstance();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bigbear776

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值