美文网首页
31 设计模式01-单例模式

31 设计模式01-单例模式

作者: 张力的程序园 | 来源:发表于2020-08-11 11:31 被阅读0次

单例模式,顾名思义,就是无论采用何种方式去创建,都要确保只能创建出一个对象出来。

  • 1 饿汉模式:类被加载的时候就去创建对象,典型的以空间换时间,故不存在线程安全问题;但创建出来的对象有可能不被用到,就失去了延迟创建的好处。
public class Student {
    private static Student instance = new Student();
    private Student(){}
    public static Student getInstance()
    {
        return instance;
    }
}
  • 2 饱汉模式:用对象的时候再去创建,具备了延迟创建的好处,但在用户第一次使用这个对象的时候要忍受创建对象的时间,省了空间,费了时间;且解决了一定的线程安全的问题。
public class Student {
    private static Student instance = null;
    private Student(){}
    public static synchronized Student getInstance() {
        if(instance == null){
            instance = new Student();
        }
        return instance;
    }
}

给getInstance方法加synchronized的原因在于保证任何一个瞬间只能有一个线程进来创建对象,但这样的加锁方式太重。

  • 3 double check:双重检查,轻量级加锁方式
public class Student {
    private static Student instance = null;
    private Student(){}
    public static Student getInstance() {
        if(instance==null)//避免每次进来都先加锁
        {
            synchronized (instance)
            {
                if(instance == null)//确保没有对象才去执行创建对象语句
                {
                    instance = new Student();
                }
            }
        }
        return instance;
    }
}
  • 4 双重加锁方式也只是解决了大部分的线程安全问题,但因为以下的原因:
    (1) 编译器优化了程序指令, 以加快cpu处理速度.
    (2) 多核cpu动态调整指令顺序, 以加快并行运算能力.
    可能出现以下的问题:
    (1)线程A, 发现对象未实例化, 准备开始实例化
    (2)由于编译器优化了程序指令, 允许对象在构造函数未调用完前, 将共享变量的引用指向部分构造的对象, 虽然对象未完全实例化, 但已经不为null了.
    (3)线程B, 发现部分构造的对象已不是null, 则直接返回了该对象.
    解决这个问题,需要指令不会因编译器的优化而省略,且要求每次直接读值。volatile关键字就能做到这件事情。所以,代码优化为如下:
public class Student {
    private volatile static Student instance = null;
    private Student(){}
    public static Student getInstance() {
        if(instance==null)//避免每次进来都先加锁
        {
            synchronized (instance)
            {
                if(instance == null)//确保没有对象才去执行创建对象语句
                {
                    instance = new Student();
                }
            }
        }
        return instance;
    }
}
  • 5 使用静态内部类
public class Student{
    private Student(){}

    private static class SingleTonHolder{
        private static Student instance = new Student();
    }

    public static Student getInstance(){
        return SingleTonHolder.instance;
    }
}

外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化instance,故而不占内存,而当Student第一次被加载时,并不需要去加载SingleTonHolder,只有当getInstance()方法第一次被调用时,才会去初始化instance,第一次调用getInstance()方法会导致虚拟机加载SingleTonHolder类,这种方法不仅能确保线程安全,也能保证单例的唯一性,同时也延迟了单例的实例化,但静态内部类单例没发传递参数。

  • 6 使用枚举完成单例
public class TestEnum{
    public static void main(String[] args) {
        Student student1 = StudentEnum.SINGLETON.getInstance();
        Student student2 = StudentEnum.SINGLETON.getInstance();
        System.out.println(student1 == student2);
    }
}

enum  StudentEnum {
    SINGLETON;
    private Student student = null;
    private StudentEnum(){
        student = new Student();
    }
    public Student getInstance(){
        return student;
    }
}
class Student{
}

以上就是实现单例的多种方式。

相关文章

  • 31 设计模式01-单例模式

    单例模式,顾名思义,就是无论采用何种方式去创建,都要确保只能创建出一个对象出来。 1 饿汉模式:类被加载的时候就去...

  • 单例模式Java篇

    单例设计模式- 饿汉式 单例设计模式 - 懒汉式 单例设计模式 - 懒汉式 - 多线程并发 单例设计模式 - 懒汉...

  • python中OOP的单例

    目录 单例设计模式 __new__ 方法 Python 中的单例 01. 单例设计模式 设计模式设计模式 是 前人...

  • 单例

    目标 单例设计模式 __new__ 方法 Python 中的单例 01. 单例设计模式 设计模式设计模式 是 前人...

  • 设计模式 - 单例模式

    设计模式 - 单例模式 什么是单例模式 单例模式属于创建型模式,是设计模式中比较简单的模式。在单例模式中,单一的类...

  • 设计模式

    常用的设计模式有,单例设计模式、观察者设计模式、工厂设计模式、装饰设计模式、代理设计模式,模板设计模式等等。 单例...

  • 2018-04-08php实战设计模式

    一、单例模式 单例模式是最经典的设计模式之一,到底什么是单例?单例模式适用场景是什么?单例模式如何设计?php中单...

  • python 单例

    仅用学习参考 目标 单例设计模式 __new__ 方法 Python 中的单例 01. 单例设计模式 设计模式设计...

  • 基础设计模式:单例模式+工厂模式+注册树模式

    基础设计模式:单例模式+工厂模式+注册树模式 单例模式: 通过提供自身共享实例的访问,单例设计模式用于限制特定对象...

  • 单例模式

    JAVA设计模式之单例模式 十种常用的设计模式 概念: java中单例模式是一种常见的设计模式,单例模式的写法...

网友评论

      本文标题:31 设计模式01-单例模式

      本文链接:https://www.haomeiwen.com/subject/esyedktx.html