首页
题库
公司真题
专项练习
面试题库
在线编程
面试
面试经验
AI 模拟面试
简历
求职
学习
基础学习课
实战项目课
求职辅导课
专栏&文章
竞赛
我要招人
发布职位
发布职位、邀约牛人
更多企业解决方案
AI面试、笔试、校招、雇品
HR免费试用AI面试
最新面试提效必备
登录
/
注册
Kitebin
深圳大学 C++
发布于广东
关注
已关注
取消关注
@猿兄:
轻松手写单例模式的6种实现方式!再也不怕面试官问了!
之前分享:高频Java基础面试题高频Java集合面试题 今天分享一些面试高频的单列模式的6种实现方式。 整理分享不易,先点赞评论收藏支持一波再看鸭~ 文章目录: 一、单例模式的定义 定义: 确保一个类只有一个实例,并提供该实例的全局访问点。 这样做的好处是:有些实例,全局只需要一个就够了,使用单例模式就可以避免一个全局使用的类,频繁的创建与销毁,耗费系统资源。 二、单例模式的设计要素 一个私有构造函数 (确保只能单例类自己创建实例) 一个私有静态变量 (确保只有一个实例) 一个公有静态函数 (给使用者提供调用方法) 简单来说就是,单例类的构造方法不让其他人修改和使用;并且单例类自己只创建一个实例,这个实例,其他人也无法修改和直接使用;然后单例类提供一个调用方法,想用这个实例,只能调用。这样就确保了全局只创建了一次实例。 三、单例模式的6种实现及各实现的优缺点 (一)懒汉式(线程不安全) 实现: public class Singleton { private static Singleton uniqueInstance; private Singleton() { } public static Singleton getUniqueInstance() { if (uniqueInstance == null) { uniqueInstance = new Singleton(); } return uniqueInstance; }} 说明: 先不创建实例,当第一次被调用时,再创建实例,所以被称为懒汉式。 优点: 延迟了实例化,如果不需要使用该类,就不会被实例化,节约了系统资源。 缺点: 线程不安全,多线程环境下,如果多个线程同时进入了 if (uniqueInstance == null) ,若此时还未实例化,也就是uniqueInstance == null,那么就会有多个线程执行 uniqueInstance = new Singleton(); ,就会实例化多个实例; (二)饿汉式(线程安全) 实现: public class Singleton { private static Singleton uniqueInstance = new Singleton(); private Singleton() { } public static Singleton getUniqueInstance() { return uniqueInstance; }} 说明: 先不管需不需要使用这个实例,直接先实例化好实例 (饿死鬼一样,所以称为饿汉式),然后当需要使用的时候,直接调方法就可以使用了。 优点: 提前实例化好了一个实例,避免了线程不安全问题的出现。 缺点: 直接实例化好了实例,不再延迟实例化;若系统没有使用这个实例,或者系统运行很久之后才需要使用这个实例,都会操作系统的资源浪费。 (三)懒汉式(线程安全) 实现: public class Singleton { private static Singleton uniqueInstance; private static singleton() { } private static synchronized Singleton getUinqueInstance() { if (uniqueInstance == null) { uniqueInstance = new Singleton(); } return uniqueInstance; }} 说明: 实现和 线程不安全的懒汉式 几乎一样,唯一不同的点是,在get方法上 加了一把 锁。如此一来,多个线程访问,每次只有拿到锁的的线程能够进入该方法,避免了多线程不安全问题的出现。 优点: 延迟实例化,节约了资源,并且是线程安全的。 缺点: 虽然解决了线程安全问题,但是性能降低了。因为,即使实例已经实例化了,既后续不会再出现线程安全问题了,但是锁还在,每次还是只能拿到锁的线程进入该方***使线程阻塞,等待时间过长。 (四)双重检查锁实现(线程安全) 实现: public class Singleton { private volatile static Singleton uniqueInstance; private Singleton() { } public static Singleton getUniqueInstance() { if (uniqueInstance == null) { synchronized (Singleton.class) { if (uniqueInstance == null) { uniqueInstance = new Singleton(); } } } return uniqueInstance; } } 说明: 双重检查数相当于是改进了 线程安全的懒汉式。线程安全的懒汉式 的缺点是性能降低了,造成的原因是因为即使实例已经实例化,依然每次都会有锁。而现在,我们将锁的位置变了,并且多加了一个检查。 也就是,先判断实例是否已经存在,若已经存在了,则不会执行判断方法内的有锁方法了。 而如果,还没有实例化的时候,多个线程进去了,也没有事,因为里面的方法有锁,只会让一个线程进入最内层方法并实例化实例。如此一来,最多最多,也就是第一次实例化的时候,会有线程阻塞的情况,后续便不会再有线程阻塞的问题。 为什么使用 volatile 关键字修饰了 uniqueInstance 实例变量 ? uniqueInstance = new Singleton(); 这段代码执行时分为三步: 为 uniqueInstance 分配内存空间 初始化 uniqueInstance 将 uniqueInstance 指向分配的内存地址 正常的执行顺序当然是 1>2>3 ,但是由于 JVM 具有指令重排的特性,执行顺序有可能变成 1>3>2。单线程环境时,指令重排并没有什么问题;多线程环境时,会导致有些线程可能会获取到还没初始化的实例。例如:线程A 只执行了 1 和 3 ,此时线程B来调用 getUniqueInstance(),发现 uniqueInstance 不为空,便获取 uniqueInstance 实例,但是其实此时的 uniqueInstance 还没有初始化。 解决办法就是加一个 volatile 关键字修饰 uniqueInstance ,volatile 会禁止 JVM 的指令重排,就可以保证多线程环境下的安全运行。 优点: 延迟实例化,节约了资源;线程安全;并且相对于 线程安全的懒汉式,性能提高了。 缺点: volatile 关键字,对性能也有一些影响。 (五)静态内部类实现(线程安全) 实现: public class Singleton { private Singleton() { } private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getUniqueInstance() { return SingletonHolder.INSTANCE; }} 说明: 首先,当外部类 Singleton 被加载时,静态内部类 SingletonHolder 并没有被加载进内存。当调用 getUniqueInstance() 方法时,会运行 return SingletonHolder.INSTANCE; ,触发了 SingletonHolder.INSTANCE ,此时静态内部类 SingletonHolder 才会被加载进内存,并且初始化 INSTANCE 实例,而且 JVM 会确保 INSTANCE 只被实例化一次。 优点: 延迟实例化,节约了资源;且线程安全;性能也提高了。 (六)枚举类实现(线程安全) 实现: public enum Singleton { INSTANCE; //添加自己需要的操作 public void doSomeThing() { }} 说明: 默认枚举实例的创建就是线程安全的,且在任何情况下都是单例。 优点: 写法简单,线程安全,天然防止反射和反序列化调用。 防止反序列化序列化:把java对象转换为字节序列的过程;反序列化: 通过这些字节序列在内存中新建java对象的过程;说明: 反序列化 将一个单例实例对象写到磁盘再读回来,从而获得了一个新的实例。我们要防止反序列化,避免得到多个实例。枚举类天然防止反序列化。其他单例模式 可以通过 重写 readResolve() 方法,从而防止反序列化,使实例唯一重写 readResolve() : private Object readResolve() throws ObjectStreamException{ return singleton;} 四、单例模式的应用场景 应用场景举例: 网站计数器。 应用程序的日志应用。 Web项目中的配置对象的读取。 数据库连接池。 多线程池。 ...... 使用场景总结: 频繁实例化然后又销毁的对象,使用单例模式可以提高性能。 经常使用的对象,但实例化时耗费时间或者资源多,如数据库连接池,使用单例模式,可以提高性能,降低资源损坏。 使用线程池之类的控制资源时,使用单例模式,可以方便资源之间的通信。 以上就是单例模式的6中实现方式了,好好理解一下,下次面试问这个就一点不虚了! 看完之后,如果还有什么不懂的,可以在评论区留言,会及时回答更新。 最后,记得点赞评论收藏支持一波鸭~
点赞 11
评论 3
全部评论
推荐
最新
楼层
暂无评论,快来抢首评~
相关推荐
07-22 11:24
门头沟学院 Java
百度提前批
想问一下友友们如果拒绝面试会影响正式批吗?会不会不让我投递正式批了
点赞
评论
收藏
分享
昨天 10:39
门头沟学院 Java
PDD笔试
求问佬PDD笔试内容是啥呀、这种测试会有挂掉的风险吗
投递拼多多集团-PDD等公司10个岗位
点赞
评论
收藏
分享
07-15 18:31
已编辑
广东科贸职业学院 嵌入式硬件工程师
求内推
求捞: 求职岗位:能学习到东西就行(可接受出差)期望薪资:到手4-5k专业:嵌入式技术应用学历:专科期望工作地:广州
点赞
评论
收藏
分享
06-27 00:18
南京信息工程大学 Java
腾讯是这样会被约面吗
投递腾讯等公司10个岗位
点赞
评论
收藏
分享
昨天 17:54
上海交通大学 无线通信工程师
实习生秒变leader
家人们谁懂啊,现在实习的小厂让我把手头项目整理出来给公司立项然后给我分配人手然后给我转正继续做这个然后做成产品实习生直接变leader笑鼠
程序员小白条:
上交的含金量,他很懂啊
实习生的蛐蛐区
点赞
评论
收藏
分享
评论
点赞成功,聊一聊 >
点赞
收藏
分享
评论
提到的真题
返回内容
全站热榜
更多
1
...
百度提前批一面 7.24
9602
2
...
字节复活赛
7555
3
...
百度一二面凉经
6228
4
...
不懂来大厂实习究竟能学到啥?
3946
5
...
滴滴提前批面经
3701
6
...
入我滴滴!早十晚六 !
3339
7
...
字节生活服务(杭州)一二三面(等HR or 挂)
3093
8
...
百度提前批一面:面试官居然让我手撕两数之和???最奇幻的一轮面试,结束还说.......
3075
9
...
滴滴提前批面经
2898
10
...
百度一面面经7.14
2776
创作者周榜
更多
正在热议
更多
#
哪些公司开提前批了?
#
26399次浏览
264人参与
#
华子oc时间线
#
1244252次浏览
6484人参与
#
风评不好的公司,你会去吗?
#
61412次浏览
443人参与
#
哪些公司校招卡第一学历
#
68278次浏览
268人参与
#
实习如何「偷」产出?
#
51109次浏览
1336人参与
#
除了主业以外,你还有哪些其他收入?
#
12126次浏览
201人参与
#
不卡学历的大厂有哪些?
#
29306次浏览
229人参与
#
校招阶段,学历VS技术哪个更重要?
#
17742次浏览
188人参与
#
职场新人体验
#
26013次浏览
249人参与
#
腾讯音乐求职进展汇总
#
98154次浏览
570人参与
#
社恐入职新公司如何融入团队
#
11931次浏览
63人参与
#
校园里的破防时刻
#
11436次浏览
128人参与
#
Offer比较,你最看重什么?
#
191627次浏览
1301人参与
#
你投递的公司有几家约面了?
#
108951次浏览
779人参与
#
你觉得技术面多长时间合理?
#
100268次浏览
720人参与
#
你的秋招第一场笔试是哪家
#
147808次浏览
1484人参与
#
实习时,大家都怎么称呼自己的mentor?
#
43774次浏览
277人参与
#
你最满意的offer薪资是哪家公司?
#
33108次浏览
176人参与
#
你今年的平均薪资是多少?
#
134040次浏览
686人参与
#
正在实习的碎碎念
#
1454806次浏览
13469人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务