《Head First设计模式》 读书笔记06 单件模式 Singleton Pattern
《Head First设计模式》 读书笔记06 单件模式 Singleton Pattern
单件模式 Singleton Pattern
类只存在一个实例,即只可以创建一个对象。
有一些类如果创造出多个对象就会导致许多问题的产生,如程序的行为异常、资源使用过量,或者是不一致的结果。
单件模式常常被用来管理共享的资源,例如数据库连接或者线程池。
单件模式的实现是通过private构造函数,类中含有一个静态方法getInstance(),调用这个方法可以创建并返回唯一的对象,也可能返回的是已经创建好的对象。
单件模式的简要定义
单件模式确保一个类只有一个实例,并提供一个全局访问点。
单件模式的实现
单件模式,首先要限制从外部创建对象,所以将构造方法声明为私有private,这样就只能在类内部调用构造函数。
如何调用这个构造函数?要使用这个类,而又没有这个类的对象,所以需要一个静态的方法,这个方法调用私有的构造函数,并且返回唯一的单件对象。
唯一的对象保存在类内,多次创建时,返回的是同一个对象。
单件模式实现1
根据上述内容,一种单件实现方式如下:

//第一种实现,多线程存在问题 class Singleton { private static Singleton singleton; private Singleton() { } public static Singleton getInstance() { if(singleton == null) { singleton = new Singleton(); } return singleton; } }
但是这种实现方式存在问题,在多线程的情况下,可能会创建多个对象。
怎么解决多线程单件问题呢?下面有三种方法:
单件模式实现2
通过synchronized关键字解决多线程问题:

//第二种实现,通过synchronized关键字解决多线程问题 //synchronized关键字迫使每个线程在进入方法前,要先等候别的线程离开该方法 //也就是说,不会有两个线程可以同时进入这个方法 //PS:同步会降低性能 class Singleton { //private static Singleton singleton = new Singleton(); private static Singleton singleton; private Singleton() { } public static synchronized Singleton getInstance() { if(singleton == null) { singleton = new Singleton(); } return singleton; } }
这种方法会造成性能的降低。一旦对象被创建,仍然多次进行同步,是一种累赘。
单件模式实现3
使用双重检查加锁(double-checked locking),首先检查实例是否已经创建了,如果尚未创建,才进行同步。这样一来,只有第一次会同步。

//第三种实现,利用双重检查加锁 //在getInstance()中减少使用同步 //注意:双重检查加锁不适用于java1.4以及之前的版本 class Singleton { //Volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。 //即阻止线程为了优化性能而保有变量的私有拷贝 private volatile static Singleton singleton; private Singleton() { } public static Singleton getInstance() { if(singleton == null)//检查实例,如果不存在就进入同步区块 { //注意,只有第一次才彻底执行这里的代码 synchronized(Singleton.class) { if(singleton == null)//进入区块后,再检查一次 { singleton = new Singleton(); } } } return singleton; } }
单件模式实现4
第四种实现是将对象的创建提前完成,用时返回,也被称为“急切”创建实例的方法。

//第四种实现,将实例化操作提前 //在静态初始化的时候创建单件,保证线程安全 class Singleton { private static Singleton singleton = new Singleton(); private Singleton() { } public static Singleton getInstance() { return singleton; } }
其他相关问题
类加载器class loader可能会导致单件失效。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了