多种单例模式实现方法详解——java代码
来源:互联网 发布:下载软件管理器 编辑:程序博客网 时间:2024/05/20 20:03
单例模式大致可以归纳为以下集中实现方式:简单懒汉模式、简单饿汉模式、同步懒汉模式、双重检验懒汉模式、静态内部类懒汉模式、枚举模式;
以上各个单例之间的关系可以归纳如下,我们假设getInstance()方法为获得实例的接口:
简单懒汉模式是很多初学者最快会想到的办法。
简单懒汉模式代码:
public class SingleInstance { private static SingleInstance instance; private SingleInstance() {} public static SingleInstance getInstance() { if (instance == null) { instance = new SingleInstance(); } return instance; }}
简单懒汉模式存在问题:假设以下情况,线程A、B同时调用getInstance(),且同时到达if (instance == null),则此时两个线程都可以进入该if语句的代码,则会产生两个实例(假设先到的线程是A,A产生了一个实例放在instance中,然后返回,随后B也产生了一个实例放在instance中,把A产生的实例覆盖掉了,然后返回,则AB两个线程拿到了两个不同的实例),因此存在同步问题。
有两个方向可解决该问题,改进懒汉模式或直接使用饿汉模式:
简单懒汉模式—(解决同步问题)—>同步懒汉模式
同步懒汉模式代码:
public class SingleInstance { private static SingleInstance instance; private SingleInstance() {} public static synchronized SingleInstance getInstance() { if (instance == null) { instance = new SingleInstance(); } return instance; }}
没错就是加了一个syn关键字,变成了同步的方法,同步懒汉模式存在的问题:假定以下情况,当instance为空时,线程A、B同时调用getInstance(),为避免产生两个实例,此时同步是需要的,但是当instance已经存在,A、B两个线程同时调用getInstance()时,必须等其中一个线程调用完,第二个线程才能调用,此时这个同步是不需要的,因为instance存在的情况下,if (instance == null)当中的代码将不会执行,即不会出现同步问题,A和B线程可以同时调用getInstance,但是因为syn无法同时调用,严重影响效率;
简单懒汉模式—(解决同步问题)—>简单饿汉模式
简单饿汉模式代码:
public class SingleInstance { private static SingleInstance instance = new SingleInstance(); private SingleInstance() {} public static synchronized SingleInstance getInstance() { return instance; }}
简单饿汉模式:在类加载的时候就会初始化需要的实例,避免了同步问题,同时保证了有且只有一个实例,但是类的加载完成到类真正的被使用还有一段时间,理论上这段时间内,instance存不存在无所谓,因为不会被调用,而在饿汉模式中instance自类被加载就会一直存在,在内存中占据位置,会影响效率(实际开发中如果需要的实例不是特别巨大的话,这种方式是一个可行的方式);
同步懒汉模式—(解决效率问题)—>双重检验懒汉模式
双重检验懒汉模式代码如下:
public class SingleInstance { private static SingleInstance instance; private SingleInstance() {} public static SingleInstance getInstance() { if (instance == null) { synchronized (SingleInstance.class) { if (instance == null) { instance = new SingleInstance(); } } } return instance; }}
双重检验懒汉模式解决了效率问题,当instance不存在时,假设A、B同时调用getInstance(),会发生阻塞,先调用同步块中的内容的线程会生产一个实例,后调用同步块中的内容的线程在同步块中因为第二个 if (instance == null)不符合转了个圈就走了,当instance存在时,因为第一个 if (instance == null)不符合,因此不会进入同步块,也就不会有阻塞的问题,这个逻辑之下,第一次新建instance时可能会阻塞,随后调用的时候都不会阻塞,同时兼顾了同步和效率问题。可能存在的问题即JVM对代码重排序,这一点我们暂且不表。
简单饿汉模式—(解决存储效率问题)—>静态内部类饿汉模式
静态内部饿汉模式如下:
public class SingleInstance { private static class Instance{ private static SingleInstance instance = new SingleInstance(); } private SingleInstance() {} public static SingleInstance getInstance() { return Instance.instance; }}
静态内部类饿汉模式利用静态内部类的特点——当被使用是,才会被加载、初始化,成功的在getInstance()第一次被调用时加载Instance并初始化instance,解决了过早产生instance影响存储效率的问题,同时因为instance是静态变量,不会有第二个产生,保证了是单例模式。该方法可能有的问题和以上所有方法实现单例子是一样的,即可能通过反射来破解单例的限制,为了保证不被反射攻击,在相关书籍中出现了基于枚举的单例,因对基于枚举的单例不太熟悉,回头再补。
所以总结一下,各个实现单例的方式之间有如下关系:
简单懒汉模式—(解决同步问题)—>同步懒汉模式—(解决效率问题)—>双重检验懒汉模式
—(解决同步问题,或者说用饿汉模式就不存在同步问题,其实和懒汉模式并没有什么先后关系)—>简单饿汉模式—(解决存储效率问题)—>静态内部类饿汉模式
—(解决反射问题)—>基于枚举单例
阅读全文
1 0
- 多种单例模式实现方法详解——java代码
- JAVA设计模式——单例(Singleton)模式 多种实现方法
- Java实现多种单例模式SingletonPattern
- 单例模式多种方法
- java 多种单例模式
- 第二篇:Java实现多种单例模式SingletonPattern
- 单例模式的多种实现方式
- 单例模式的多种实现
- 单例模式的多种实现方式
- 单例模式的多种实现
- 单例设计模式多种实现方式
- 【单例模式】的多种实现方式
- 单例模式(Java代码实现)
- java 单例模式 几个实现方法
- java单例模式实现方法
- 架构设计之设计模式 (四) Java中多种方式实现单例模式
- 单例模式—java实现
- 译——Singletons (单例模式多种方式分析)
- thinkphp view层和控制器层2
- 神经网络笔记
- 线程安全和可重入函数
- apk反编译教程
- freebuf上一篇关于waf绕过的介绍
- 多种单例模式实现方法详解——java代码
- 开篇第一章<简要IOT技术栈分析>
- RabbitMQ系列
- kaldi006 -- 构图
- Hdu2018 母牛的故事
- 如何解决wireshark抓包大于mtu的问题
- 关于网页消息提示音问题解决与实现
- C++容器vector的常用成员函数
- Linux(centos7)安装redis及第一个helloWorld