Java学习笔记(十三):浅谈单例模式

什么是单例模式?

指一个类只有一个实例,且该类能自行创建这个实例的一种模式。例如,Windows 中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。

在计算机系统中,还有 Windows 的回收站、操作系统中的文件系统、多线程中的线程池、显卡的驱动程序对象、打印机的后台处理服务、应用程序的日志对象、数据库的连接池、网站的计数器、Web 应用的配置对象、应用程序中的对话框、系统中的缓存等常常被设计成单例。

单例模式的实现方式

饿汉模式(线程安全)

饿汉式在类初始化的时候就创建了对象,加载到了内存。因为对象已经创建好了,饿汉式是可以保证线程安全的。
但是在没有使用这个对象的情况下就加载到内存是一种很大的浪费。

要想让一个类只能构建一个对象,自然不能让它随便去做new操作,因此Signleton的构造方法是私有的

public class Singleton {
    private Singleton() {}  //私有构造函数
    private static Singleton instance = null;  //单例对象
    //静态工厂方法
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
懒汉模式(最优)即 线程安全的双重检查锁单例
public class Singleton {
    private static volatile Singleton instance = null;
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

1.为了防止new Singleton被执行多次,因此在new操作之前加上Synchronized 同步锁,锁住整个类。
2.第一次判断 if (instance ==null) 的原因:在第一次之后,instance已经不再为null,直接执行return语句
3.第二次判断if (instance == null) 的原因:当一个线程在创建一个对象后,由于其他线程已经在第一轮判断时就进入了方法,所以其他线程会继续走synchronized代码块,这时进行第二轮判断,其他线程会在第二轮判断时发现对象已经创建,则不会再继续创建对象。
4.使用volatile 的原因:

java中简单的一句 instance = new Singleton,会被编译器编译成如下JVM指令:
memory =allocate(); //1:分配对象的内存空间
ctorInstance(memory); //2:初始化对象
instance =memory; //3:设置instance指向刚分配的内存地址

但是这些指令顺序并非一成不变,有可能会经过JVM和CPU的优化,指令重排成下面的顺序:

memory =allocate(); //1:分配对象的内存空间
instance =memory; //3:设置instance指向刚分配的内存地址
ctorInstance(memory); //2:初始化对象

如果当线程A执行完1,3,时,instance对象还未完成初始化,但已经不再指向null。此时如果线程B抢占到CPU资源,执行 if(instance == null)的结果会是false,从而返回一个没有初始化完成的instance对象。

经过volatile的修饰,当线程A执行instance = new Singleton的时候,JVM执行顺序始终保证是下面的顺序:
memory =allocate(); //1:分配对象的内存空间
ctorInstance(memory); //2:初始化对象
instance =memory; //3:设置instance指向刚分配的内存地址

可以避免返回一个没有初始化完成的instance对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值