Java 设计模式--单例模式

来源:互联网 发布:运筹学与控制论 知乎 编辑:程序博客网 时间:2024/06/03 22:04

在 《Head First 设计模式》 中这么定义单例模式:
单件模式确保一个类只有一个实例,并提供一个全局访问点

单件模式特点

  1. 单例类只能有一个实例,只允许该类自己管理一个实例,同时避免其他类再自行产生实例,要想取得单件实例,通过单件类是唯一的途径。
  2. 有一个全局访问点,当你需要实例时,向类查询,它就返回单件实例。

类图

这里写图片描述
1. 其中这个 uniqueInstance 类变量持有唯一的单件实例。
2. getInstance 方法是静态的,这意味着它是一个类方法,所以可以在代码的任何位置使用 Singleton.getInstance() 访问它,并返回单件实例。

懒汉式单例

package com.example.administrator.myprofile;/** * 文 件 名: Singleton * 创 建 人: Bradley * 创建日期: 2017/10/13 21:59 * 修改时间: * 修改备注: */public class Singleton {    /**     * 利用一个静态变量来记录 Singleton 类的唯一实例     */    private static  Singleton uniqueInstance;    /**     *将构造器设为私有的,只有 Singleton 内才能调用构造器     */    private Singleton(){};    /**     * 用 getInstance 来实例化这个对象,并将这个对象返回     * @return Singleton     */    public static Singleton getInstance(){        if (uniqueInstance == null) {            uniqueInstance = new Singleton();        }        return uniqueInstance;    }} 

懒汉式是典型的时间换空间,就是每次获取实例都会进行判断,看时候需要创建实例,浪费判断时间。请注意,如果我们不需要这个实例,它就永远不会产生。这就是 “延迟实例化” (lazy instantiaze) 。

饿汉式单例

package com.example.administrator.myprofile;/** * 文 件 名: Singleton * 创 建 人: Bradley * 创建日期: 2017/10/13 21:59 * 修改时间: * 修改备注: */public class Singleton {    /**     * 在静态初始化器中创建单件,这段代码保证了线程安全     */    private static  Singleton uniqueInstance = new Singleton();    /**     *将构造器设为私有的,只有 Singleton 内才能调用构造器     */    private Singleton(){};    /**     * 用 getInstance 来实例化这个对象,并将这个对象返回     * @return Singleton     */    public static Singleton getInstance(){        return uniqueInstance;  //已经有了实例,直接返回    }}

利用这个做法,我们依赖 JVM 在加载这个类时马上创建此唯一的单件实例。JVM 保证在任何线程访问 uniqueInstance 静态变量之前,一定先创建实例。
饿汉式是典型的控件换时间,当类装载的时候就创建类的实例,不管你用不用,先创建出来,然后每次调用的时候,就不需要再判断,节省了运行时间。

双重检查加锁

所谓“双重检查加锁”机制,指的是:并不是每次进入 getInstance 方法都需要同步,而是先不同步,进入方法后,先检查实例是否存在,如果不存在才进行下面的同步块,这是第一重检查,进入同步块过后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。这样一来,就只需要同步一次了,从而减少了多次在同步情况下进行判断所浪费的时间。
“双重检查加锁”机制的实现会使用关键字 volatile,它的意思是:被 volatile 修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。

package com.example.administrator.myprofile;/** * 文 件 名: Singleton * 创 建 人: Bradley * 创建日期: 2017/10/13 21:59 * 修改时间: * 修改备注: */public class Singleton {    private volatile static  Singleton uniqueInstance ;    /**     *将构造器设为私有的,只有 Singleton 内才能调用构造器     */    private Singleton(){};    /**     * 第一步:检查实例,如果不存在,就进入同步区块     * 第二步:进入同步区块后,再检查一次,如果仍是 null ,才创建实例     * @return Singleton     */    public static Singleton getInstance(){        if (uniqueInstance == null) { //只有第一次才彻底执行这里的代码            synchronized (Singleton.class) {                if (uniqueInstance == null) {                    uniqueInstance = new Singleton();                }            }        }        return uniqueInstance;  //已经有了实例,直接返回    }}