设计模式(5)——单例模式的七种实现方式
定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
单例模式结构图:
单例模式有多种写法各有利弊,现在我们来看看各种模式写法。
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关键字的可以自己网络检索查询;在这里使用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() { } }
调用方法:
public class Main {public static void main(String[] args) {Singleton.INSTANCE.doSomething();}}
默认枚举实例的创建是线程安全的,并且在任何情况下都是单例,上述讲的几种单例模式实现中,有一种情况下他们会重新创建对象,那就是反序列化,将一个单例实例对象写到磁盘再读回来,从而获得了一个实例。反序列化操作提供了readResolve方法,这个方法可以让开发人员控制对象的反序列化。在上述的几个方法示例中如果要杜绝单例对象被反序列化是重新生成对象,就必须加入如下方法:
private Object readResolve() throws ObjectStreamException{ return singleton; }
枚举单例的优点就是简单,但是大部分应用开发很少用枚举,可读性并不是很高,不建议用。
最后借用 《Effective Java》一书中的话,
单元素的枚举类型已经成为实现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获取对象对应类型的对象。这种方式使得我们可以管理多种类型的单例,并且在使用时可以通过统一的接口进行获取操作,降低了用户的使用成本,也对用户隐藏了具体实现,降低了耦合度。
总结
到这里七中写法都介绍完了,至于选择用哪种形式的单例模式,取决于你的项目本身,是否是有复杂的并发环境,还是需要控制单例对象的资源消耗。
设计模式(5)——单例模式的七种实现方式相关推荐
- Java设计模式之单例模式(七种写法)
Java设计模式之单例模式(七种写法) 第一种,懒汉式,lazy初始化,线程不安全,多线程中无法工作: public class Singleton {private static Singleton ...
- Java23种设计模式之单例模式的五种实现方式、反射破解单例模式、不能破解枚举单例模式详解
源码链接(Gitee码云):https://gitee.com/oldou/javadesignpatterns 这里有我整理好的Java23种设计模式的源码以及博客教程,博客教程中介绍了Java23 ...
- java单例模式的七种写法_Java设计模式之单例模式的七种写法
什么是单例模式? 单例模式是一种常见的设计模式,单例模式的写法有很多种,这里主要介绍三种: 懒汉式单例模式.饿汉式单例模式.登记式单例 . 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类 ...
- Java面试23种设计模式之单例模式的8种实现方式
单例模式8中实现方式 1.单例模式介绍 2.单例模式的八种方式 3.饿汉式(静态常量),这种单例模式可用,可能造成内存浪费. 4.饿汉式(静态代码块),这种单例模式可用,可能造成内存浪费. 5.懒汉式 ...
- 单例模式的七种实现方式,你学废了吗?
单例模式 什么是单例模式,概念就不多做描述了,直接头铁冲代码- 一.饿汉式(饿鬼投胎,程序一启动就创建单例) 饿汉式单例模式,是饿汉式:程序一启动就加载 饿汉式起码能保证单例,虽然会浪费内存,但是会保 ...
- 3种设计模式java小程序_Java设计模式之单例模式(3种实现方式)
饿汉模式 public class Singleton {//实例化private static Singleton instance=new Singleton();private Singleto ...
- python实现单例模式的几种方式_基于Python中单例模式的几种实现方式及优化详解...
单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场. ...
- python创建单例模式_Python单例模式的四种创建方式实例解析
单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场. ...
- 单例模式的四种实现方式(饿汉模式、懒汉模式、静态内部类、枚举类)
首先,设计模式是我们程序员在软件开发过程中面临的一般问题的解决方案,通过学习设计模式可以使我们在编程时更加有条理性,同时培养我们写代码的思维能力,从而提高我们的工作效率.接下来就跟着博主的脚步往下走吧 ...
- 【设计模式】叩心自问:什么是设计模式? 设计模式的目的是什么?设计模式依据哪些(七种)原则设计的?设计模式有哪些?分类?
aas 叩心自问 1 :设计模式的目的是什么? 叩心自问 2 :什么是设计模式? 叩心自问 3:设计模式依据哪些(七种)原则设计的? 3.1.单一职责原则 3.2.接口隔离原则 3.3.依赖倒转原则 ...
最新文章
- H5 自动播放背景音频,兼容安卓和苹果手机, ios createInnerAudioContext 无法自动播放解决
- java 线程组和线程_Java多线程 线程组原理及实例详解
- GP TEE_ObjectInfo结构体在不同的版本之间的变化
- 【Centos 8】【Centos 7】安装 docker
- e课表项目第二次冲刺周期第四天
- import pycharm setting_Pycharm不能正常使用的常见问题
- 设计模式17_命令模式
- python程序打包exe
- linux rz上传文件及出错解决方案
- bootstrap树节点如何设置默认不展开_我开源了一个基于Vue的组织架构树组件
- 联想笔记本安装xp sp3 GHOST版无法安装声卡问题
- 经济统计学专业学C语言,经济统计学专业有哪些课程
- Linus ,扎克伯格,雷军等巨佬的办公桌
- 基频和倍频的概念_基频峰,泛频峰,倍频峰,二倍频峰的区别
- Java网络编程——基本网络支持
- Vue 按enter键实现登陆
- python爬取豆瓣电视剧页面
- 2022年上海落户全部方式!落户上海政策变化及条件汇总!
- 机器学习 - SVD
- c语言黑白棋程序设计报告,C语言游戏编程 黑白棋游戏