单例模式

Posted fengwbetter

tags:

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

目录

前言

在特定场景下,我们需要在全局使用某一个对象的同一个实例,我们就需要保证一个对象不能存在多个实例。单例模式是一种很常见的设计模式;比如Servlet在Tomcat中是单例的,Spring IOC容器管理的Bean默认是单例的;单例模式就是为了保证一个对象对外只提供一个实例;单例模式实现方式比较多。

破坏单例

存在以下几种破坏单例的情况:

1.关键字new通过构造方法 2.多线程环境 3.反序列化 4.复制(clone) 5.反射

在实际应用中,实现单例模式时通常只需要考虑 1和2 两种情况;

实现单例模式

根据实例化的时间不同可分为两大类:

一是饿汉模式,这种方式在类加载阶段完成实例化;

二是懒汉模式,这种方式在使用的时候才去实例化。

单例模式的懒汉写法:

/**
 * 单例模式——懒汉
 * 双重校验
 */
class Singleton01 {
    /**
     * 使用volatile修饰的原因(禁止指令重排)
     * 指令重排有可能导致先将未初始化的对象的引用赋值给instance变量,再进行初始化
     * 也就是说可能出现一个线程还未对对象进行初始化,另外一个线程由于判断instance不为空于是获得了一个未初始化的对象
     */
    private static volatile Singleton01 instance = null;
    /**
     * 私有化构造函数
     */
    private Singleton01(){
        System.out.println("我被实例化了");
    }
    public static  Singleton01 getInstance(){
        //如果还未实例化,则进行同步(因为实际上实例化成功之后就不需要进行同步操作了)
        if(null == instance){
            synchronized(Singleton01.class){
                //最外层的判断没有进行同步,是非线程安全的,这里再次进行判断
                if(null == instance){
                    instance = new Singleton01();
                }
            }
        }
        return instance;
    }

}

单例模式的饿汉写法:

/**
 * 单例模式-饿汉
 * 
 */

class Singleton02 {
    /**
     * 在类加载初始化阶段实例化
     * 在这个阶段由于虚拟机已经进行了同步,因此是线程安全的
     */
    private static Singleton02 instance = new Singleton02();
    /**
     * 私有化构造函数
     */
    private Singleton02(){
        System.out.println("我被实例化了");
    }
    public static Singleton02 getInstance(){
        return instance;
    }

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

常用代码片段

性能比较好的单例写法

片段作为 Android 中的单例

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

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

单例模式以及静态代码块