单例模式

来源:互联网 发布:吴裕彬 水平 知乎 编辑:程序博客网 时间:2024/06/06 01:12

本文链接地址

单例模式

一,定义确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例

二,目的避免产生多个对象消耗过多的资源

三,关键点

3.1 构造函数不对外开放,一般为Private

3.2 通过一个静态方法或者美剧返回单例类对象

3.3 确保单例类的对象有且只有一个,尤其是在多线程环境下

3.4 确保单例类在反序列化时不会重新构建对象四,实现方式

四,实现方式

4.1 懒汉模式 

public class SingleTon {private static SingleTon mSingleTonInstance;private SingleTon(){}public static synchronized SingleTon getInstance(){if (mSingleTonInstance == null) {mSingleTonInstance = new SingleTon();}return mSingleTonInstance;}}



优点:单例只有在使用时才会被实例化
缺点:第一次加载时需要及时进行实例化,反应稍慢,最大的问题是每次调用getInstance都进行同步,造成不必要的同步开销

不建议使用
4.2 Double Check Lock(DCL)实现单例
public class SingleTonDCL {// private static SingleTonDCL mSingleTonDCLInstance;private volatile static SingleTonDCL mSingleTonDCLInstance;private SingleTonDCL(){}public static SingleTonDCL getInstance(){if (mSingleTonDCLInstance == null) {synchronized (SingleTonDCL.class) {if (mSingleTonDCLInstance == null) {/*** 下面这行代码,做了三件事情* 1,给SingleTonDCL的实例分配内存* 2,调用SingleTonDCL()的构造函数,初始化成员字段* 3,将mSingleTonDCLInstance对象指向分配的内存空间(此时mSingleTonDCLInstance不再是null)* ===============================================================================* 因为JVM编译器允许处理器乱序执行,以及JDK1.5之前JVM中Cache、寄存器到主内存会写顺序的规定,上面2和3的执行顺序是无法保证的,* 所以需要使用volatile关键字*/mSingleTonDCLInstance = new SingleTonDCL();}}}return mSingleTonDCLInstance;}}



既能够在需要时才初始化单例,又能保证线程安全,且在单例对象初始化后调用getInstance不进行同步锁



优点:资源利用率高,第一次执行getInstance时单例对象才会被实例化,效率高
缺点:第一次加载时反应稍慢,也由于Java内存模型的原因偶尔失败,在高并发环境下也有一定的缺陷,虽然发生概率很小

4.3 静态内部类单例模式

/*** 静态内部类单例模式* Created by liubo on 2017/9/7.*/public class SingleTonStaticInner {private static SingleTonStaticInner mSingleTonStaticInner;private SingleTonStaticInner(){}public static SingleTonStaticInner getInstance(){return SingleTonStaticInnerHolder.mSingleTonStaticInner;}/*** 静态内部类*/private static class SingleTonStaticInnerHolder{private static final SingleTonStaticInner mSingleTonStaticInner = new SingleTonStaticInner();}}






上面的实现方式中,为了防止在反序列的时候重新生成对象,需要加入如下方法

private Object readResolve() throws ObjectStreamException{return mInstance;}





4.4 枚举

public enum SingleTonEnum {INSTANCE;public void doSomething(){Log.d("Demo", "we can do what we want");}}