Java设计模式【单例模式】
Java设计模式【单例模式】
单例模式
单例模式(Singleton Pattern)是一种创建型设计模式,其主要目的是确保一个类只有一个实例,并提供对该实例的唯一访问点。
优缺点
优点
:
(资料图片)
提供了对唯一实例的受控访问。
由于在系统内存中只存在一个对象,因此可以节约系统资源。
缺点
:
单例类的扩展有很大的困难。
单例类的职责过重,在一定程度上违背了“单一职责原则”。
对象生命周期。 单例模式没有提出对象的销毁,在提供内存的管理的开发语言中,只有单例模式对象自己才能将对象实例销毁,因为只有它拥有对实例的引用。 在各种开发语言中,比如C++,其他类可以销毁对象实例,但是这么做将导致单例类内部的指针指向不明。
单例模式的使用
饿汉模式
- 静态成员变量
/** * @author Physicx * @date 2023/5/12 下午10:13 * @desc 单例 * Created with IntelliJ IDEA */public class Singleton { //初始化实例对象 private static final Singleton instance = new Singleton(); //私有化构造方法 private Singleton() { } //提供获取实例对象方法 public static Singleton getInstance() { return instance; }}
- 静态代码块
/** * @author Physicx * @date 2023/5/12 下午10:13 * @desc 单例 * Created with IntelliJ IDEA */public class Singleton { //实例对象 private static final Singleton instance; static { instance = new Singleton(); } //私有化构造方法 private Singleton() { } //提供获取实例对象方法 public static Singleton getInstance() { return instance; }}
饿汉式单例的写法适用于单例对象较少的情况,这样写可以保证绝对的线程安全,执行效率比较高。但是缺点也很明显,饿汉式会在类加载的时候就将所有单例对象实例化,这样系统中如果有大量的饿汉式单例对象的存在,系统初始化的时候会造成大量的内存浪费,换句话说就是不管对象用不用,对象都已存在,占用内存。
懒汉模式
public class Singleton { //实例对象 private static Singleton instance; //私有化构造方法 private Singleton() { } //提供获取实例对象方法(线程安全) public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }}
线程安全的一种懒汉式写法,在类第一次使用的时候初始化,获取实例的静态方法由synchronized修饰,所以是线程安全的。这种方法每次获取实例对象都加锁同步,效率较低。
双重检测机制(DCL)
public class Singleton { //实例对象 private static volatile Singleton instance; //私有化构造方法 private Singleton() { } //提供获取实例对象方法 public static Singleton getInstance() { if (instance == null) { //加锁处理 synchronized (Singleton.class) { if (instance==null) { //初始化 instance = new Singleton(); } } } return instance; }}
实例对象必须用 volatile
修饰,否则极端情况可能出现安全隐患。
以上初始化对象代码被编译后会变成以下三条指令:
分配对象的内存空间。
初始化对象。
设置instance指向刚才分配的内存空间。
如果按照上面的执行顺序则不加volatile没有问题,但是CPU或编译器为了提高效率,可能会进行指令重排,最终顺序变为:
分配对象的内存空间。
设置instance指向刚才分配的内存空间。
初始化对象。
当两个线程同时获取实例对象时,线程A已经将instance指向分配空间但未初始化对象,线程B此时第一次判空已不为空,于是返回instance实例,但是此时返回的实例未初始化会导致后续空指针异常。
DCL这种方式同样也是类第一次使用的时候初始化,初始化代码synchronized修饰线程安全,这种方式只会第一次实例对象才会进行同步,因此效率高。
《Java Concurrency in Practice》作者Brian Goetz在书中提到关于DCL的观点:促使DCL模式出现的驱动力(无竞争同步的执行速度很慢,以及JVM启动时很慢)已经不复存在,因而它不是一种高效的优化措施。延迟初始化占位类模式(静态内部类)能带来同样的优势,并且更容易理解。
静态内部类(延迟初始化)
public class Singleton { //私有化构造方法 private Singleton(){} //静态内部类(被调用时加载) private static class SingletonHandle { private static final Singleton instance = new Singleton(); } //提供获取实例对象方法 public static Singleton getInstance() { return SingletonHandle.instance; }}
利用静态内部类被调用时才加载的特性,通过静态初始化初始Singleton对象,由于JVM将在初始化期间获得一个锁,并且每个线程都至少获取一次这个锁以确保这个类已经加载,因此在静态初始化期间,内存写入操作将自动对所有线程可见。因此无论是在被构造期间还是被引用时,静态初始化的对象都不需要显式的同步。
线程安全,效率高,使用的时候才会初始化不浪费内存。
《Java Concurrency in Practice》作者Brian Goetz 推荐这种单例实现方式。
枚举实现方式
除了以上几种常见的实现方式之外,Google 首席 Java 架构师、《Effective Java》一书作者、Java集合框架的开创者Joshua Bloch在Effective Java一书中提到:单元素的枚举类型已经成为实现Singleton的最佳方法。
在这种实现方式中,既可以避免多线程同步问题;还可以防止通过反射和反序列化来重新创建新的对象。
public class Singleton { //私有化构造方法 private Singleton() {} enum SingletonEnum { SINGLETON; private final Singleton instance; SingletonEnum() { instance = new Singleton(); } //提供获取实例对象方法 public Singleton getInstance() { return instance; } }}
调用方式如下:
public static void main(String[] args) { Singleton instance1 = Singleton.SingletonEnum.SINGLETON.getInstance(); Singleton instance2 = Singleton.SingletonEnum.SINGLETON.getInstance(); System.out.println(instance2 == instance1); }
普通的单例模式是可以通过反射和序列化/反序列化来破解的,jvm虚拟机会保证枚举类型不能被反射并且构造函数只被执行一次,而Enum由于自身的特性问题,是无法破解的。当然,由于这种情况基本不会出现,因此我们在使用单例模式的时候也比较少考虑这个问题。
总结
实现方式 | 优点 | 缺点 |
---|---|---|
饿汉模式 | 线程安全,效率高 | 非懒加载 |
懒汉模式 | 线程安全,懒加载 | 效率低 |
双重检测机制 | 线程安全,懒加载,效率高 | |
静态内部类 | 线程安全,懒加载,效率高 | |
枚举 | 线程安全,效率高 | 非懒加载 |
由于单例模式的枚举实现代码比较简单,而且又可以利用枚举的特性来解决线程安全和单一实例的问题,还可以防止反射和反序列化对单例的破坏,因此在很多书和文章中都强烈推荐将该方法作为单例模式的最佳实现方法。
参考:单例模式详解(知乎文章)
设计模式相关其他文章:Java设计模式总结
标签:
-
Java设计模式【单例模式】
-
学生事务管理的流派与模式_环球即时看
-
天舟文化05月12日主力资金大幅流出-焦点热议
-
天天热文:如何布局下半年?券商中期策略看点多多 A股新一轮盈利周期逐步启动
-
“小电梯”提升“大幸福”!宝山又有2处多层住宅将加装电梯-环球短讯
-
全球快消息!中兢大汽亮相第十七届深圳国际充电设施产业展览会
-
江苏如东:做靓“土特牌” 唱响“致富经”_天天热门
-
江苏南通:金融活水“贷”动经济回暖向好
-
云内德润混动点燃绿色“新引擎”
-
终端份额26.3% 一汽解放连续4个月持续领先 环球滚动
-
如皋入选第二批国家创新型县(市)建设名单
-
引导海内外启商回乡创业 通商总会启东商会成立
-
营造“有诺必践”信用环境 南通市一案例获评全国优秀
-
天天微头条丨近三年崇川建设用地地均GDP产出水平提升13%
-
今日快看!特斯拉宣布在西班牙推出家用电池组Powerwall
-
庄菁雄成为上汽通用第七任总经理|天天播报
-
“新能源汽车检测与维修岗课赛证融通系列教材”发布
-
当前信息:滚滚车辙,烙印时代记忆
-
美公共充电桩遭遇成长的烦恼-天天速看
-
环球热点!专论 || 从零部件进出口看中国汽车产业链