Java版单例模式与涉及到的相关知识

介绍:

单例模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

饿汉式:


public class SingleModel {
 
   // 创建 SingleModel 的一个对象,加载类时就进行初始化
   private static SingleModel instance = new SingleModel ();
 
   // 让构造函数为 private,这样此类就不能在外部实例化
   private SingleModel (){}
 
   // 获取唯一可用的对象
   public static SingleModel getInstance(){
      return instance;
   }
 
   public void show(){
      System.out.println("这是单例-饿汉式!");
   }
}

当外部想使用此类的show()方法时,只能通过SingleModel.getInstance()获取实例对象再进行.show()方法调用

懒汉式:

1.第一版 [不支持多线程 ]


public class Singleton {  

    private static Singleton instance;  
    private Singleton (){}  
    
    public static Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}

低配:不支持多线程。

2.第二版 [使用synchronized加锁保证在多线程下单例,但影响效率]


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

3.双重校验锁(DCL,即 double-checked locking) [使用volatile禁止指令重排 ]


public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
        if (singleton == null) {  
        
        	// 此处分三步:                  			| 可能重排指令:
            //(1)分配内存                 			| (1)分配内存
            //(2)创建对象在内存           	        | (2)instance指向该内存位置
            //(3)instance指向该内存位置              | (3)创建对象在内存
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
}

创建一个对象并不是原子操作,单线程的指令重排没有问题,但是多线程时,某一个线程在执行到第一次检测,读取到的instance不为null时,instance的引用对象可能没有完成初始化。

指令重排:是指JVM在编译Java代码时,或者CPU在执行JVM字节码的时候,对现有的指令顺序进行重新排序。其目的是为了在不改变程序执行结果的前提下,优化程序的运行效率。【需要注意的是,这里所说的不改变执行结果,指的是不改变单线程下的程序执行结果】

有空可以了解一下内存屏障

volatile特性之一:
保证变量在线程之间的可见性。可见性的保证是基于CPU的内存屏障指令,被JSR-133抽象为happens-before原则。
volatile特性之二:
阻止编译时和运行时的指令重排。编译时JVM编译器遵循内存屏障的约束,运行时依靠CPU屏障指令来阻止重排。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值