设计模式-单例

Posted 番茄红了

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式-单例相关的知识,希望对你有一定的参考价值。

定义

确保一个类只有一个实例,并提供一个全局访问点

类图

在这里插入图片描述
构成:

  1. 私有构造器
  2. 静态方法
  3. 静态变量

代码

基础版

public class Singleton{
    
    //利用静态变量来记录Singleton类的唯一实例
    private static Singleton uniqueInstance;
    
    //声明私有构造器,私有在Singleton类中才可以调用该方法
    private Singleton(){}
    
    //实例化对象,并返回该示例
    public static Singleton getInstance(){
        if(uniqueInstance==null){
            uniqueInstance=new Singleton();
        }
        return uniqueInstance;
    }
}

基础版的缺点?
多线程会实例化出多个对象。

  • 如果现在有多个线程,并且都在未实例化对象前进入,则都不满足uniqueInstance==null的条件,那么就会根据线程创建出多个实例对象。

解决线程问题版本

同步getInstance方法

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

更改点:

  • synchornized(同步锁):
    使用该关键字使得每个线程在进入这个方法之前,需要等候别的线程离开该方法(加锁)。线程进到该方法就加锁,
    等前面的线程处理完,再让后续访问的线程进入该方法

该方法有缺点吗?

  • 有的。 同步会减低性能:https://www.zhihu.com/question/29802671/answer/1265735136

急切实例化(改善多线程)

public class Singleton{
    
    //在静态初始化器中创建单件,此段代码JVM保证了线程安全
    private static Singleton uniqueInstance = new Singleton();
    
    private Singleton{};
    
    public static Singleton getInstance(){
        return uniqueInstance;
    }
}

jvm保证了线程的安全:https://www.cnblogs.com/little-mao2020/p/14673899.html
静态内部类的特点:外部类加载时不需要加载静态内部类,不被加载则不占用内存,(延迟加载)当外部类调用getInstance方法时,才加载静态内部类,静态属性保证了全局唯一,静态变量初始化保证了线程安全

双重检查加锁(改善多线程)

减少同步

public class Singleton{
    
    private volatile static Singleton uniqueInstance;
    
    private Signleton(){};
    
    public static Singleton getInstance(){
        //检查实例,如果不存在,就进入同步
        if(uniqueInstance==null){
            synchronized(Sigleton.class){
                //再检查一次,如果还是null则创建实例
                if(uniqueInstance==null){
                    uniqueInstance=new Sigleton();
                }
            }
        }
    }
}

如何减少的同步?

  • 先判断了实例是否存在,存在就不往后进行了,则线程不需要一致等待。

解决线程同步&防止序列化

public enmu Singleton{
    Instance;
    
    public void m(){};

}

以上是关于设计模式-单例的主要内容,如果未能解决你的问题,请参考以下文章

常用代码片段

性能比较好的单例写法

片段作为 Android 中的单例

单例片段或保存网页视图状态

从 Viewpager2 片段访问父片段函数

你熟悉的设计模式都有哪些?写出单例模式的实现代码