设计模式之单例设计模式笔记

单例设计模式

需求:希望某一个类只有一个唯一的实例

实现例子:

步骤
  • 将构造函数私有化
  • 在类的内部创建实例
  • 提供获取唯一实例的方法

//设计一个单例类
恶汉模式:在类加载的时候创建了唯一对象,对系统的开销相对较大,可能会产生影响软件启动的延时问题

class MySingleton{
//    instance指向唯一的实例,类加载的时候执行,只执行一次
    private static MySingleton instance=new MySingleton();
//    私有化构造方法
    private MySingleton(){    }
//    必须对外提供一个可以访问唯一实例的方法,并返回该唯一实例
    public static MySingleton getInstance(){
        return  instance;
    }
}

设计一个单例类
懒汉模式:就是在第一次调用getInstance的时候创建唯一的实例。

class MySingleton{
    private static MySingleton instance;
    private MySingleton(){}
    public static MySingleton getInstance(){
        if (instance==null){
        //stop
            instance=new MySingleton();
        }
        return instance;    }}

如果这样设计,有多个线程的话,线程A看到instance为null,因为某种原因停止(如sleep()),线程B进去。这样导致生成两个实例。
方法1:在getInsatnce()前加sychronized关键字。
方法2:
直接加上对象锁。
缺点:不管是否已经生成一个唯一的实例,都要获得对象锁。

synchronized (MySingleton02.class) {
            if (instance == null) {
                instance = new MySingleton02(); } }

方法3:
没有生成唯一的实例时,才需要获取对象锁
优点:将锁的范围缩小,提高性能
缺陷:线程A和线程B同时调用getInstance()方法,得出的结果都是null。线程A虽然先得到CPU的控制权创建对象,线程B之后也得到了CPU的控制权创建新的对象,所以返回了不只一个实例。
解决方法:用双重检测机制(DCL),再次判断是否为空

if (instance == null) {
                synchronized (MySingleton02.class) {
                    instance = new MySingleton02();}}

方法4:
双重检测机制(DCL),且加上volatile关键字,此关键字有内存屏障的功能。

class MySingleton{
    private static volatile MySingleton02 instance;
    private MySingleton(){}
    private static MySingleton02 getInstance(){
            if (instance == null) {
                synchronized (MySingleton02.class) {
                    if(instance==null){
                    instance = new MySingleton02();}
                }
            }
        return  instance;
    }
}

你可能感兴趣的:(设计模式之单例设计模式笔记)