设计模式(23种)之单例模式

设计模式:是一套被反复使用、多数人知晓的、经过分类的、代码设计经验总结。就是一些开发套路,用于解决某一些特定场景的思想。
aop:把通用的代码统一管理、动态代理、aspel等

单例模式:
保证整个程序中只有一个实例,常用的是特殊的类,比如管理类等。
1、构造函数私有,防止在外部new对象,静态类也是一个单例
2、内部必须提供一个静态的方法,让外部调用

饿汉式,不好处是,应用启动的时候,类的加载就已经new了对象(不用)

   /**
   * 单例 ——饿汉式
   * 保证只有一个实例,私有化构造函数,防止外部被new 实例化
   */
 java:
public class Singleton {
    private Singleton(){}

    private static Singleton instance =new Singleton();

    public static Singleton getInstance(){
        return instance;
    }
}
kotlin:
 class Singleton private constructor() {
          companion object{
            private val mInstance: Singleton = Singleton()
            fun getInstance(): Singleton{
                return mInstance!!
          }
      }
}

懒汉式 只有在使用的时候才会new对象,可能更加高效,用的时候才会new

问题:多线程并发的问题,线程不安全,如果有多线程还会存在多个实例。

/**
 * 单例 ——懒汉
 * 只有在使用的时候才会new对象,可能更加高效,用的时候才会new
 */
java:
public class Singleton {
    private Singleton(){}

    private static Singleton instance ;

    public static Singleton getInstance(){
        if (null == instance){
            instance = new Singleton();
        }
        return instance;
    }
}
kotlin:
class Singleton private constructor(){
    companion object{
        private var  mInstance: Singleton? = null
        fun getInstance(): Singleton{
                  if(null == mInstance){
                        mInstance = Singleton()
                 }
            return mInstance!!
        }
    }
}

解决懒汉式线程不安全,如果有多线程还会存在多个实例。添加synchronized 同步锁

问题:每次获取都会判断同步锁,效率不高。

/**
*单例 ——懒汉
*/
public class Singleton {
    private Singleton(){}

    private static Singleton instance ;

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

使用synchronized 同步锁,解决线程安全,但是效率不高问题。

下面的既保证线程安全,效率也是比较高的。
问题:但是又出现了一个问题:多线程会出现某一个线程改了共用对象(变量),短时间内另一个线程可能不可见的

/**
*单例 ——懒汉同步锁DCL
*/
public class Singleton {
    private Singleton(){}

    private static Singleton instance ;

    public static  Singleton getInstance(){
        if (null == instance){
          //第一次判断同步锁
            synchronized(Singleton.class){
                if (null == instance){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

解决出现问题

volatile关键字

用处:

1、防止重排序
2、线程可见性:某一个线程改了共用对象(变量),短时间内另一个线程可能不可见的,因为每一个线程都有自己的缓存区。
因为:实例化一个类对象,需要:
1、开辟一个内存,
2、初始化对象
3、给变量赋值(指向内存地址)
但是java多线程2和3的循环是不固定的,会出现
1、开辟一个内存,
2、给变量赋值(指向内存地址)
3、初始化对象

public class Singleton {
    private Singleton(){}

    private static volatile Singleton instance ;

    public static  Singleton getInstance(){
        if (null == instance){
          //第一次判断同步锁
            synchronized(Singleton.class){
                if (null == instance){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

静态内部类

保证了线程安全,用到的时候才会进行实例化。

/**
 * 静态内部类的形式
 * 既保证线程安全,又保证用的时候才会被实例化
 */
public class Singleton {
    
    private Singleton(){}
    
    public static  Singleton getInstance(){
        return Singletons.instance;
    }
    private static class Singletons{
        private static  volatile Singleton instance ;
    }
}

单例模式——容器管理

/**
 * 单例模式——容器管理,系统中用到
 */
public class Singleton {

    private Singleton(){}
    private static Map singleMap= new HashMap<>();
    static {
        singleMap.put("singleMap",new Singleton());
    }

    public static Object getService(){
        return singleMap.get("singleMap");
    }
}

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