《Head-First-设计模式》笔记7-单例模式

  1. 定义
  2. 饿汉式方式
  3. 懒汉式方式
  4. 使用静态的内部类作为单例
  5. 多个 class loader 环境下的单件模式

更多请查看:Effective-Java-读书笔记03-用私有构造器或者枚举类型强化Singleton属性

定义

单例模式(Singleton Pattern):单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。

饿汉式方式

//饿汉式单例
public class Singleton {
    private static Singleton singleton = new Singleton();

    private Singleton(){}

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

饿汉式是线程安全的,因为虚拟机只会装载一次,在装载类的时候不会发生并发。

懒汉式方式

/**
 * 利用双重加锁保证只在实例化变量的时候进行同步
 */
public class Singleton {

    private static volatile Singleton instance; // 定义静态实例变量
    private Singleton(){ }

    /**
     * 提供全局访问点
     * @return 该类的实例
     */
    public static Singleton getInstance(){
        if(instance == null) { // 两次判空,可以只在第一次生成对象时进入同步块,提高效率
            synchronized(Singleton.class) { // 进入同步块
                if(instance == null) // 再次判空
                    instance = new Singleton();
            }
        }
        return instance;
    }
}

http://www.infoq.com/cn/articles/double-checked-locking-with-delay-initialization

在成员变量 instance 前面加了一个 volatile 关键字,这个特别重要。在 Java 内存模型(JMM)中,并不限制处理器的指令顺序,说白了就是在不影响结果的情况下,顺序可能会被打乱。

在执行 instance = new Singleton(); 这条命令语句时,JMM 并不是一下就执行完毕的,即不是原子性,实质上这句命令分为三大部分:

  1. 为对象分配内存
  2. 执行构造方法语句,初始化实例对象
  3. 把sInstance的引用指向分配的内存空间

在 JMM 中这三个步骤中的 2 和 3 不一定是顺序执行的,如果线程 A 执行的顺序为 1、3、2,在第 2 步执行完毕的时候,恰好线程 B 执行第一次判空语句,则会直接返回 instance,那么此时获取到的 instance 仅仅只是不为 null,实质上没有初始化,这样的对象肯定是有问题的!

而 volatile 关键字的存在意义就是保证了执行命令不会被重排序,也就避免了这种异常情况的发生,所以这种获取单例的方法才是真正的安全可靠!

使用静态的内部类作为单例

public class Singleton {
    //1 私有化构造函数,内部控制创建实例的个数
    private Singleton(){}

    //2 定义方法为客户端提供类实例
    //3 需要定义成类方法,加static
    public static Singleton getIntance(){
        return SingletonInstace.instance;
    }

    //静态的内部类作为实例,一个类的静态属性只会在第一次加载类时初始化
    private static class SingletonInstace{
        static Singleton instance = new Singleton();
    }
}

多个 class loader 环境下的单件模式

如果存在多个类加载器,多个类加载器可能同时加载我们的单件类,从而产生多个实例。

对于这种情况,我们可以显式指定使用哪一个 class loader 来加载单件类,这样就有效避免了上述问题。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 bin07280@qq.com

文章标题:《Head-First-设计模式》笔记7-单例模式

文章字数:775

本文作者:Bin

发布时间:2018-07-08, 23:07:31

最后更新:2020-06-14, 22:42:50

原始链接:http://coolview.github.io/2018/07/08/Head-First-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/%E3%80%8AHead-First-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E3%80%8B%E7%AC%94%E8%AE%B07-%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录