单例模式(七种实现方法)
定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
单例模式结构图:
单例模式有多种写法各有利弊,现在我们来看看各种模式写法。
1. 饿汉模式
public class Singleton { private static Singleton instance = new Singleton(); private Singleton (){}public static Singleton getInstance() { return instance; } }
这种方式在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快。 这种方式基于类加载机制避免了多线程的同步问题,但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到懒加载的效果。
2. 懒汉模式(线程不安全)
public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
懒汉模式申明了一个静态对象,在用户第一次调用时初始化,虽然节约了资源,但第一次加载时需要实例化,反映稍慢一些,而且在多线程不能正常工作。
3. 懒汉模式(线程安全)
public class Singleton { private static Singleton instance; private Singleton (){}public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
这种写法能够在多线程中很好的工作,但是每次调用getInstance方法时都需要进行同步,造成不必要的同步开销,而且大部分时候我们是用不到同步的,所以不建议用这种模式。
4. 双重检查模式 (DCL)
public class Singleton { private volatile static Singleton singleton; private Singleton (){} public static Singleton getInstance() { if (instance== null) { synchronized (Singleton.class) { if (instance== null) { instance= new Singleton(); } } } return singleton; } }
这种写法在getSingleton方法中对singleton进行了两次判空,第一次是为了不必要的同步,第二次是在singleton等于null的情况下才创建实例。在这里用到了volatile关键字,不了解volatile关键字的可以查看Java多线程(三)volatile域这篇文章,在这篇文章提到了双重检查模式是正确使用volatile关键字的场景之一。
在这里使用volatile会或多或少的影响性能,但考虑到程序的正确性,牺牲这点性能还是值得的。 DCL优点是资源利用率高,第一次执行getInstance时单例对象才被实例化,效率高。缺点是第一次加载时反应稍慢一些,在高并发环境下也有一定的缺陷,虽然发生的概率很小。DCL虽然在一定程度解决了资源的消耗和多余的同步,线程安全等问题,但是他还是在某些情况会出现失效的问题,也就是DCL失效,在《java并发编程实践》一书建议用静态内部类单例模式来替代DCL。
5. 静态内部类单例模式
public class Singleton { private Singleton(){}public static Singleton getInstance(){ return SingletonHolder.sInstance; } private static class SingletonHolder { private static final Singleton sInstance = new Singleton(); } }
第一次加载Singleton类时并不会初始化sInstance,只有第一次调用getInstance方法时虚拟机加载SingletonHolder 并初始化sInstance ,这样不仅能确保线程安全也能保证Singleton类的唯一性,所以推荐使用静态内部类单例模式。
6. 枚举单例
public enum Singleton { INSTANCE; public void doSomeThing() { } }
默认枚举实例的创建是线程安全的,并且在任何情况下都是单例,上述讲的几种单例模式实现中,有一种情况下他们会重新创建对象,那就是反序列化,将一个单例实例对象写到磁盘再读回来,从而获得了一个实例。反序列化操作提供了readResolve方法,这个方法可以让开发人员控制对象的反序列化。在上述的几个方法示例中如果要杜绝单例对象被反序列化是重新生成对象,就必须加入如下方法:
private Object readResolve() throws ObjectStreamException{ return singleton; }
枚举单例的优点就是简单,但是大部分应用开发很少用枚举,可读性并不是很高,不建议用。
7. 使用容器实现单例模式
public class SingletonManager { private static Map<String, Object> objMap = new HashMap<String,Object>();private Singleton() { }public static void registerService(String key, Objectinstance) {if (!objMap.containsKey(key) ) {objMap.put(key, instance) ;}}public static ObjectgetService(String key) {return objMap.get(key) ;} }
用SingletonManager 将多种的单例类统一管理,在使用时根据key获取对象对应类型的对象。这种方式使得我们可以管理多种类型的单例,并且在使用时可以通过统一的接口进行获取操作,降低了用户的使用成本,也对用户隐藏了具体实现,降低了耦合度。
总结
到这里七中写法都介绍完了,至于选择用哪种形式的单例模式,取决于你的项目本身,是否是有复杂的并发环境,还是需要控制单例对象的资源消耗。
转载于:https://www.cnblogs.com/cxhfuujust/p/10878761.html
单例模式(七种实现方法)相关推荐
- C库函数qsort七种使用方法示例
这篇文章是 一楼那个学长写的 C库函数qsort七种使用方法示例 七种qsort排序方法<本文中排序都是采用的从小到大排序> 一.对int类型数组排序 C++代码 int num[10 ...
- 10截图时屏幕变大_解锁电脑更多的截屏姿势:Win 10中自带的七种截图方法
说起电脑截图,我们很容易想到的是微信中Alt+A的快捷方式,但如果我们电脑中没有安装微信却要对屏幕内容进行截图应该怎么办?马上下载并安装微信?没有那么复杂,Win 10就自带了多达七种截图方法,熟悉其 ...
- C语言运行时电脑白屏怎么办,win10电脑白屏死机无响怎么回事_win10电脑白屏死机无响七种解决方法...
win10专业版使用一段时间后出现白屏死机的问题,开机后不是登录界面,而是白色屏幕,尝试多次还是一样,怎么办呢?此故障原因无非是硬件或软件两大原因,有什么办法解决呢?此文小编告诉大家解决win10电脑 ...
- html语言单词背不下来,专八词汇背不下来?来看看这七种记忆方法
专八词汇背不下来?来看看这七种记忆方法 01 结合构词法记忆单词 前缀记忆,英语单词前缀很多. 常用前缀有: anti-(反对,防止),co-(共同),de-(离开,除去),dis-(否定,相反), ...
- 连接服务器失败请检查网络是否启用修复程序,Win10出现网络连接问题的七种修复方法...
现如今办公和生活都少不了网络,Win10电脑在连接网络时总出现连接失败,出现这种情况原因比较多,大家首先要找到故障原因,然后在对症下药来处理,今天给大家带来Win10出现网络连接问题的七种修复方法,有 ...
- Win10管理员命令提示符窗口的七种打开方法汇总
Win10管理员命令提示符窗口的七种打开方法汇总 管理员命令提示符是我们在Windows10系统操作中经常使用的功能之一, 管理员命令提示符可以非常直接的运行各种程序.命令等. 如:在管理员命令提示符 ...
- java设计模式之单例模式(七种方法)
单例模式:个人认为这个是最简单的一种设计模式,而且也是在我们开发中最常用的一个设计模式. 单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个 ...
- 常用的七种数据分析方法有哪些?
一.漏斗分析法 漏斗分析法能够科学反映用户行为状态,以及从起点到终点各阶段用户转化率情况,是一种重要的分析模型.漏斗分析模型已经广泛应用于网站和APP的用户行为分析中,例如流量监控.CRM系统.SEO ...
- 多图详解:七种具体方法增强代码可扩展性
欢迎大家关注公众号「JAVA前线」查看更多精彩分享文章,主要包括源码分析.实际应用.架构思维.职场分享.产品思考等等,同时欢迎大家加我个人微信「java_front」一起交流学习 1 六大原则 在设计 ...
最新文章
- 通信网络设计(最小生成树+图的联通)
- 网络负载均衡相关技术-DNS
- js -“=”“==”和“===”的区别
- django 基础知识 ~ forms详解
- get请求中文乱码问题
- Linux面试最常见的5个基本问题
- ConcurrentHashMap之实现细节
- sqlite3 学习
- 【实习之T100开发】T100 单档程序开发(2)添加功能
- Java开发数据库默认端口及网络常用端口号
- 轻松搭建docker应用的mesos集群
- 计算机类外文翻译论文,计算机专业毕业论文 外文翻译.doc
- 如何从0到1打磨一门 Elasticsearch 线上直播课?
- 怎样查询本机ip地址?如何利用花生壳获取外网IP教程
- 一键脚本搭建docker redis 集群(cluster)
- HTML——Header:请求头参数详解
- 微信小游戏颜色风暴自动化
- jquery系列之-ajaxSubmit()提交表单示例
- Excel自定义排序
- Unity打包Android项目报错