美文网首页
单例模式

单例模式

作者: 认真的辰 | 来源:发表于2021-11-19 01:37 被阅读0次

单例模式

一、单例概念

单例模式是一种对象创建模式,它用于产生一个对象的具体实例,确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

二、使用场景

  1. 创建一个对象会消耗过多的资源,如要访问IO和数据库等资源等,并且这个对象会被多次使用;

  2. 频繁使用的对象

  3. 某种类型的对象只应该有且只有一个。

由于new操作的次数减少,因而对系统内存的使用频率也会降低,这将减轻GC压力,缩短

GC停顿时间

三、UML类图

image

Singleton:单例类

实现单例模式主要有以下几个关键点:

  1. 构造函数不对外开发,一般为private;

  2. 通过一个静态方法或枚举返回单例类对象;

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

  4. 确保单例类对象在反序列化是不会重新构建对象。

四、单例的六种写法和各自特点

目前单例的写法有饿汉、懒汉、DCL、静态内部类、枚举、容器这六种方式。

1.饿汉模式

在JVM虚拟机加载这个类时,对象就会被实例化,不管是否使用到。(适用于创建对象不会消耗过多资源的情况)

public class HungrySingleton{    private static final HungrySingleton instance = new HungrySingleton();    private HungrySingleton(){}    public static HungrySingleton getInstance(){         return instance;    }}复制代码

不足之处:无法对instance实例做延迟加载。

2.懒汉模式

懒汉模式是声明一个静态对象,在用户第一次调用getInstance时进行初始化。

public class LazySingleton {    private static LazySingleton instance = null;    private LazySingleton(){}        //使用synchronized关键字,保证此方法时线程安全的    public static synchronized LazySingleton getInstance(){        if(instance ==null){            instance = new LazySingleton();        }        return instance;    }}复制代码

优点:单例只有在使用时才会被实例化,在一定程度上节约了资源。

缺点:第一次加载时需要及时进行实例化,反应稍慢。

不足之处:每次调用getInstance都进行同步,造成不必要的同步开销。

3.Double Check Lock(DCL)方式

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

public class DclSingleton {    private static DclSingleton instance = null;    private DclSingleton() {    }    public static DclSingleton getInstance() {        if (instance == null) {            //同步            synchronized (DclSingleton.class) {                if (instance == null) {                    instance = new DclSingleton();                }            }        }        return instance;    }}复制代码

不足之处:JVM的即时编译器中存在指令重排序的优化。下面分析一下:

假设线程A执行到instance = new DclSingleton();语句,这句代码最终会被编译成多条汇编指令,它大致做了三件事情:

1)给DclSingleton的实例分配内存;

2)调用DclSingleton的构造函数,初始化成员字段;

3)将instance对象指向分配的内存空间(此时instance就不是null)。

由于Java编译器允许处理器乱序执行,上面2、3的顺序是无法保证的。在3执行完毕,2未执行之前,切换到B线程上,这是instance已经非空;所以线程B直接取走instance,再使用时会出错;这就是DCL失效问题,而且这种错误难以跟踪难以重现,很可能会隐藏很久。

在JDK1.5之后,具体化了volatile关键字,1.5之后的版本,只需将instance的定义改成

 private volatile static DclSingleton instance = null;复制代码

就可以保证instance对象每次都是从主内存中读取,就可以用DCL的方式来完成单例模式。

4.静态内部类方式

DCL虽然在一定程度上解决了资源消耗、多余的同步、线程安全等问题,但是它还是在某些情况下出现失效的问题。

public class StaticInnerSingleton {    private StaticInnerSingleton(){}    public static StaticInnerSingleton getInstance(){        return SingletonHolder.instance;    }    private static class SingletonHolder{        private static final  StaticInnerSingleton instance= new StaticInnerSingleton();    }}复制代码

这种方式不经能够确保线程安全,也能保证单例对象的唯一性,同时也延迟了单例的实例化,推荐使用这种方式实现单例模式。

5.枚举单例

public enum EnumSingleton {    INTANCE;//定义一个枚举类的元素,它就是EnumSingleton的实例    public void doSomething(){        System.out.print("do sth.");    }}复制代码

优点:写法简单、线程安全。

枚举在Java中与普通的类一样,不仅能够有字段,还能够有自己的方法。最重要的是默认枚举实例的创建时线程安全的,并且在任何情况下它都是一个单例。

6.使用容器实现单例模式

public class SingletonManager {    private static Map<String,Object> objMap = new HashMap<>();    public static void registerService(String key,Object instance){        if(!objMap.containsKey(key)){            objMap.put(key,instance);        }    }    public static Object getService(String key){        return objMap.get(key);    }}复制代码

在程序的初始,将多种单例类型注入到一个统一的管理勒种,在使用时根据key获取对象。

此方式可以管理多种类型的单例,通过统一的接口进行获取操作,降低了使用成本及耦合度。

五、总结

实现单例模式的核心原理是将构造函数私有化,通过静态方法获取唯一的实例;在获取的过程中必须保证线程安全、防止反序列化导致重新生成实例对象等问题。

选择哪种实现方式取决于项目本身,如是否是复杂的并发环境、JDK版本是否过低、单例对象的资源消耗等。

参考文献:Android源码设计模式(第二版)

相关文章

  • 【设计模式】单例模式

    单例模式 常用单例模式: 懒汉单例模式: 静态内部类单例模式: 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/xmhstrtx.html