摘要:一为什么需要单例模式可以保证一个类仅有一个实例,控制实例数目,节约系统的资源。代码示例枚举是否多线程安全是是否初始化是描述推荐使用对于枚举类来说,每个对象都是被修饰的。在第二版的第条,推荐使用枚举实现单例模式。
一、为什么需要单例模式?
可以保证一个类仅有一个实例,控制实例数目,节约系统的资源。比如:数据库的连接池。一些资源管理器常被设计成单例模式
二、怎么使用
2.1 饿汉式
是否多线程安全:是
是否 Lazy 初始化:否
描述:
优点:没有加锁,执行效率提高
缺点:在某些情况下,不是因为调用getInstance而导致的类初始化的话,那么会存在浪费内存的情况
该模式是基于classLoader机制避免多线程的问题,当读取类的静态字段(类静态常量不是)、调用类的静态方法时(当然还有很多情况会触发类的初始化,更多细节参考深入理解JVM虚拟机)。会触发类的初始化。当进行初始化时,JVM会为类的静态语句块和为类变量赋值操作,生成
备注:有人说在类加载时就会初始化,浪费内存,个人感觉是不对的。首先JVM的类加载会进行类的加载(加载class文件),验证(验证字节码文件),准备(为类变量分配内存并赋初值),解析(将符号引号转为直接引用);紧接着再初始化,但是需要注意的是,已经说明JVM什么时候才会为类进行初始化。所以,说类在加载时就会初始化,个人感觉是不对的。如果个人讲述错误,请留言
代码示例:
public class Singleton { private static Singleton instance = new Singleton(); private Singleton (){} public static Singleton getInstance() { return instance; } }
2.2、静态内部类
是否多线程安全:是
是否 Lazy 初始化:是
代码示例:
public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }
2.3、双检锁/双重检验锁(DCL,double checked locking)
是否多线程安全:是
是否 Lazy 初始化:是
描述:
缺点:实现复杂,且效率过低,每次都需要判断一次if。不推荐使用
请注意
如果singleton变量没有加上volatile,那么就是非线程安全的。来模拟一下:
线程A走到④处,初始化完毕了singleton,线程B走到②处。因为没有加volatile,所以此时singleton可能不会对其他内存立即可见,所以线程B也走到了④,因此,实例化了2个对象。
代码示例:
public class Singleton { private volatile static Singleton singleton; private Singleton (){} public static Singleton getSingleton() { if (singleton == null) { ① synchronized (Singleton.class) { ② if (singleton == null) { ③ singleton = new Singleton(); ④ } } } return singleton; } }
2.4、枚举
是否多线程安全:是
是否 Lazy 初始化:是
描述:推荐使用
对于枚举类来说,每个对象(INSTANCE)都是被public static final修饰的。其次构造函数默认私有。所以用来实现单例模式,是非常适合的。
在Effective Java第二版的第77条,推荐使用枚举实现单例模式。
代码示例:
public enum Test{ INSTANCE; private Singleton singleton; Test() { singleton = new Singleton; } public Singleton getInstance() { return singleton; } }
有关参考:
java并发编程实战
EffectiveJava 第二版
http://www.runoob.com/design-...
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/67845.html
该文章属于《编程中的那些经典套路——设计模式汇总》系列,并且以下内容基于语言PHP 在设计模式中,单例模式和工厂模式)可以说是使用的最普遍的设计模式了,所以掌握此种模式尤为重要。 单例模式一般使用在资源共享和需要控制资源的情况下。 例如:购物车,回收站,数据库连接池,计数器,配置文件共享等所有项目中只需要存在一个的模块,你都可以采用单例模式。 单例模式的好处就在于当前进程只产生一个对象(或者叫...
摘要:在写单例模式的代码之前,我们先简单了解一下两个知识点,关于类的加载顺序和关键字。懒汉和饿汉在程序编写上,一般将单例模式分为两种,分别是饿汉式和懒汉式,饿汉式在类加载时就完成了初始化,所以类加载比较慢,但获取对象的速度快。 定义 单例模式是比较常见的一种设计模式,目的是保证一个类只能有一个实例,而且自行实例化并向整个系统提供这个实例,避免频繁创建对象,节约内存。 单例模式的应用场景很多, 比如...
摘要:枚举单例以上是一个单例枚举的例子,而我们要获取该实例只需要,并且此种方式可以保证该单例线程安全防反射攻击防止序列化生成新的实例。 关于单例模式,相信大家都所有了解,比较经典的实现有饿汉式、借助内部类、双重锁检测,这些实现可以保证线程安全,但是在某些特殊情况下并不能够保证仅仅只有一个单例,因为像序列化、反射攻击等往往可以生成新的实例对象,本文将重点分析枚举单例模式如何防止反射攻击。 枚...
摘要:本篇文章总结了目前主流的实现单例模式的方法供读者参考。使用实现单例模式同样,我们在类的创建时进行干预,从而达到实现单例的目的。 很多初学者喜欢用 全局变量 ,因为这比函数的参数传来传去更容易让人理解。确实在很多场景下用全局变量很方便。不过如果代码规模增大,并且有多个文件的时候,全局变量就会变得比较混乱。你可能不知道在哪个文件中定义了相同类型甚至重名的全局变量,也不知道这个变量在程序的某...
阅读 2671·2021-11-25 09:43
阅读 2579·2021-11-22 09:34
阅读 2823·2021-11-12 10:34
阅读 1430·2021-10-20 13:46
阅读 2300·2019-08-30 13:21
阅读 929·2019-08-30 11:21
阅读 483·2019-08-30 11:20
阅读 2186·2019-08-29 17:20