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

设计模式-单例模式

作者: 圣村的希望 | 来源:发表于2019-10-22 08:31 被阅读0次

  单例模式是在全局拥有唯一一个实例,这个唯一是有相对性的。有时候需要在系统中拥有一个实例,例如配置信息这些等。单例模式就是保证一个类仅有一个实例,并且提供一个全局访问点。
  单例模式的几种实现方式:

  • 单线程安全简易模式:懒汉模式
public class Singleton {

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

    这个是最容易想到的实现方式,但是往往最容易想到的模型,就会很容易出现问题。这个实现方式在单线程模式下运行没有问题,但是在多线程环境下就会出现线程安全问题。

  • 多线程安全模式:
public class Singleton {

    private static Singleton instance = null;

    private Singleton() {}

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

    为了在多线程下并发安全,在方法的前面加上synchronized,这样通过synchronized关键字来保证线程的并发安全。优点是实现方式简单,但是缺点是对所有的读和写都加锁串行化,导致并发效率不高,本来instance已经实例化,getInstance就是一个读操作,这样并不需要加锁,所以接下来进行优化。

public class Singleton {
    //这里的静态变量要加volatile关键字
    private static volatile Singleton instance = null;

    private Singleton() {}

    public static Singleton getInstance() {
        //保证了读的无锁划处理,instance不为空直接返回
        if (instance == null) {
            //保证写操作的串行化处理
            synchronized (Singleton.class) {
                //获取到静态类锁之后,要判断是否前面的线程已经实例化
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

    DCL双重锁实现方式,对静态变量采用volatile关键字来进行修饰,保证了内存可见性和防止指令重排序操作,因为new Singleton()操作不是原子性的,他是在内存中分配空间,然后是实例化等操作,再就是将引用指向对应的内存空间。所以在这个时候可能发生指令重排序,就需要volatile关键字来保证。并且还让其他线程能对instance实例及时感应。

  • 类变量加载时初始化:饿汉模式,线程安全
public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return instance;
    }
}

    这个是在Singleton类被加载准备阶段就进行实例化,静态类变量和类的静态代码块在类加载准备阶段的时候,他会被jvm搜集起来构成类的构造函数<cinit>然后被执行,所以他是靠jvm来保证线程安全的,实现起来很简单方便,但是他是饿汉模式,在类被加载的时候就被初始化了。

  • 静态内部类的实现方式:懒汉模式,线程安全
public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }

    private static class SingletonHolder {
        private static final Singleton instance = new Singleton();
    }
}

    这个其实还是靠jvm在加载类的时候来保证线程安全性以保证全局唯一,只不过他是懒汉模式,还是在getInstance的时候才会被初始化实例。
单例模式存在的问题:
    这里面的单例是具有相对性的,在java中不同的类加载器在加载同一个类的时候,也会被认为是不同的实例,所以在实现单例模式的时候,不同的类加载器会导致在同一个jvm实例下类的实例并不是唯一的。
    Spring中实现单例的方式是通过容器来实现的,他是通过一个全局的ConcurrentHashMap容器来存放所有类的实例,类的完全路径作为key来保证全局唯一,这样就可以解决不同类加载器加载类导致的问题。

相关文章

  • 单例模式Java篇

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

  • python中OOP的单例

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

  • 单例

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

  • 设计模式 - 单例模式

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

  • 设计模式

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

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

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

  • python 单例

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

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

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

  • 单例模式

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

  • 设计模式之单例模式

    单例设计模式全解析 在学习设计模式时,单例设计模式应该是学习的第一个设计模式,单例设计模式也是“公认”最简单的设计...

网友评论

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

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