美文网首页
单例模式

单例模式

作者: dlihasa | 来源:发表于2019-07-09 16:03 被阅读0次

单例模式的定义

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

单例模式的使用场景

确保某个类有且只有一个对象的场景,避免产生多个对象消耗过多的资源。

实现单例模式主要的关键点

(1)构造函数不对外开放,一般为private;
(2)通过一个公开的静态方法或者枚举返回单例类对象;
(3)确保单例类对象有且只有一个,尤其是在多线程环境下;
(4)确保单例类对象在反序列化时不会重新构建对象。

单例类的五种实现方式(这里只展示五种)

  • (1)饿汉式
public class Singleton {
    
    private static Singleton mInstance = new Singleton();
    
    private Singleton(){}
    
    public static Singleton getInstance(){
        return mInstance;
    }
}

饿汉式特点:直接new一个单例类的实例对象,在使用时直接获取。

  • (2)懒汉式
public class Singleton {
    
    private static Singleton mInstance = null;
    
    private Singleton(){};
    
    public static synchronized Singleton getInstance(){
        if(mInstance==null){
            mInstance = new Singleton();
        }
        return mInstance;
    }
}

懒汉式特点:懒汉式的优点是单例只在使用时才会被实例化,在一定程度上节约了资源;缺点是第一次加载时需要及时进行实例化,反应稍慢,最大的问题是每次调用getInstance方法都进行同步,造成不必要的同步开销。

  • (3)Double Check Lock(DCL,双重检查锁)实现单例
public class Singleton {

    private volatile static Singleton mInstance = null;
    
    private Singleton(){};
    
    public static Singleton getInstance(){
        if(mInstance==null){//避免不必要的同步
            synchronized(Singleton.class){
                if(mInstance==null){//获取锁之后,判断在mInstance为null的情况下实例化
                    mInstance = new Singleton();
                }
            }
        }
        return mInstance;
    }
}

volatile关键字是jdk1.5之后添加的,这样定义的对象在多线程下每次都是从主内存(进程内存)中去获取最新的实例(因为其他线程可能有修改了)
DCL实现单例特点:优点是资源利用率高,第一次执行getInstance时单例对象才会被实例化,效率高;缺点是第一次加载时反应稍慢,由于java内存模型的原因偶尔会失败(并发场景十分复杂或者低于JDK6版本使用)

  • (4)静态内部类实现单例
    《Java并发编程实践》一书中指出DCL虽然解决了很多问题,但是仍然存在双重检查锁定失效,并建议使用静态内部类来实现单例模式:
public class Singleton {

    private Singleton(){};
    
    public static Singleton getInstance(){
        return SingletonHolder.mInstance;
    }
    
    private static class SingletonHolder{
        private static final Singleton mInstance = new Singleton();
    }
}

非静态内部类(对象级内部类)必须绑定在外部类对象实例上,而静态内部类(类级内部类)不存在依赖,和其他外部类一样,在第一次使用时装载,直接创建。
具体来说,当第一次加载Singleton类时并不会初始化mInstance,只有在第一次调用Singleton的getInstance方法时才会导致mInstance被初始化(第一次调用getInstance方法会导致虚拟机加载SingletonHolder类,加载类时会初始化静态域,也就是说会初始化mInstance),这种方式不仅能够确保线程安全,也能够保证单例对象的唯一性,同时也延迟了单例的实例化(在使用时采取初始化单例对象)

  • (5)枚举单例
    上述几个方式在反序列化的时候会重新创建对象,但是默认的枚举实例的创建是线程安全,并且在任何情况下都是单例。

在Android中的单例模式

Android的系统核心服务都是以单例形式存在的,比如ActivityManagerService、WindowManagerService、LayoutInflater等等。

总结

单例模式中DCL双重检查锁定实现单例静态内部类实现单例两种方式使用最多,在这些实现方式中,我们不难看出,Java基础的重要性(Java内存模型、原子操作、类加载等),有两本书还是需要去看一看《深入理解java虚拟机》 《Java并发编程实践》

相关文章

  • 【设计模式】单例模式

    单例模式 常用单例模式: 懒汉单例模式: 静态内部类单例模式: Android Application 中使用单例模式:

  • Android设计模式总结

    单例模式:饿汉单例模式://饿汉单例模式 懒汉单例模式: Double CheckLock(DCL)实现单例 Bu...

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

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

  • 设计模式之单例模式详解

    设计模式之单例模式详解 单例模式写法大全,也许有你不知道的写法 导航 引言 什么是单例? 单例模式作用 单例模式的...

  • Telegram开源项目之单例模式

    NotificationCenter的单例模式 NotificationCenter的单例模式分析 这种单例模式是...

  • 单例模式Java篇

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

  • IOS单例模式的底层原理

    单例介绍 本文源码下载地址 1.什么是单例 说到单例首先要提到单例模式,因为单例模式是单例存在的目的 单例模式是一...

  • 单例

    iOS单例模式iOS之单例模式初探iOS单例详解

  • 单例模式

    单例模式1 单例模式2

  • java的单例模式

    饿汉单例模式 懒汉单例模式

网友评论

      本文标题:单例模式

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