大家好,我是小简,这一篇文章,6种单例方法一网打尽,虽然单例模式很简单,但是也是设计模式入门基础,我也来详细讲讲。
(资料图)
DEMO仓库:https://github.com/JanYork/DesignPattern ,欢迎PR,共建。
单例模式(SingletonPattern
)是 Java
中最简单的设计模式之一。
单例模式一共存在 --> 懒汉式、饿汉式、懒汉+同步锁、双重校验锁、静态内部类、枚举这六种方式。
这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。
这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
Spring
的Bean
默认就是单例的,全局唯一。单例的原理非常简单,我们让他唯一的方法就是让他不可用被new
,那我们只需要私有化类的构造即可:
private ClassName() {}
但是私有化后,我们不能new
又如何创建对象呢?
我们首先要明白,private
他是私有的,也就是不让外部其他类访问,那我们自己还是可以访问的,所以在上文的要求中就说到了:单例类必须自己创建自己的唯一实例。
同时我们还需要抛出单例的获取方法。
public class SlackerStyle {}
public class SlackerStyle { private static SlackerStyle instance;}
public class SlackerStyle { private static SlackerStyle instance; /** * 私有化构造方法(防止外部new新的对象) */ private SlackerStyle() { }}
public class SlackerStyle { private static SlackerStyle instance; /** * 私有化构造方法(防止外部new新的对象) */ private SlackerStyle() { } /** * 提供一个静态的公有方法,当使用到该方法时,才去创建instance * 即懒汉式 * * @return instance(单例对象) */ public static SlackerStyle getInstance() { if (instance == null) { instance = new SlackerStyle(); } return instance; }}
当我们调用静态方法,它便会判断上面的静态属性
instance
中有无自身对象,无 --> 创建对象并赋值给instance
,有 --> 返回instance
。
优点:延迟加载,效率较高。缺点:线程不安全,可能会造成多个实例。
解释:延迟加载 --> 懒汉式只有在需要时才会创建单例对象,可以节约资源并提高程序的启动速度。
在以上的类中,对getInstance()
方法添加synchronized
锁,即可弥补线程不安全缺陷。
/** * 注意,此段为补充,为了解决线程不安全的问题,可以在方法上加上synchronized关键字,但是这样会导致效率下降 * 提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题 * 此方法为线程安全的懒汉式,即懒汉+同步锁,就不额外写一个类了 * * @return instance(单例对象) */ public static synchronized SlackerStyle getInstance2() { if (instance == null) { instance = new SlackerStyle(); } return instance; }
虽然弥补了线程不安全的缺陷,但是也失去了一部分效率,所以需要根据业务环境去选择适合的方法,鱼和熊掌不可兼得。
还是如开始一样,创建好单例类,私有化构造方法。
public class HungryManStyle { /** * 私有化构造方法(防止外部new新的对象) */ private HungryManStyle() { }}
我们饿汉式是延迟加载的,即要用,然后第一次去调用时才会创建对象,而饿汉式恰恰相反,他在初始化类的时候就去创建。
我们的static
关键词修饰的方法或属性,在类加载之初遍开辟内存创建好了相关的内容了。
包括每个类的:
static{}
中也一样的。
所以我们直接使用static
修饰。
public class HungryManStyle { /** * 静态变量(单例对象),类加载时就初始化对象(不存在线程安全问题) */ private static final HungryManStyle INSTANCE = new HungryManStyle(); /** * 私有化构造方法(防止外部new新的对象) */ private HungryManStyle() { } /** * 提供一个静态的公有方法,直接返回INSTANCE * * @return instance(单例对象) */ public static HungryManStyle getInstance() { return INSTANCE; }}
而且我们在类的静态属性创建时就new
了一个自身对象了。
饿汉式的优点如下:
线程安全:由于在类加载时就创建单例对象,因此不存在多线程环境下的同步问题。没有加锁的性能问题:饿汉式没有使用同步锁,因此不存在加锁带来的性能问题。实现简单:饿汉式的实现比较简单,不需要考虑多线程环境下的同步问题。饿汉式的缺点如下:
立即加载:由于在类加载时就创建单例对象,因此可能会影响程序的启动速度。浪费资源:如果单例对象很大,并且程序中很少使用,那么饿汉式可能会浪费资源。综上所述,饿汉式的优点是线程安全、没有加锁的性能问题和实现简单,缺点是可能影响程序的启动速度和浪费资源。
在选择单例模式的实现方式时,需要根据实际情况综合考虑各种因素,选择最适合的方式。
老规矩。
public class DoubleLockStyle { /** * volatile关键字,使得instance变量在多个线程间可见,禁止指令重排序优化 * volatile是一个轻量级的同步机制,即轻量锁 */ private static volatile DoubleLockStyle instance; /** * 私有化构造方法(防止外部new新的对象) */ private DoubleLockStyle() { }}
不一样的是,我在属性上使用volatile
关键词修饰了。
补充知识啦!
在这个代码中,使用了 volatile 关键字来确保 instance 变量的可见性,避免出现空指针异常等问题。
volatile
是一种修饰符,用于修饰变量。当一个变量被声明为volatile
时,线程在访问该变量时会强制从主内存中读取变量的值,而不是从线程的本地缓存中读取。使用volatile
关键字可以保证多线程之间的变量访问具有可见性和有序性。在对该变量进行修改时,线程也会将修改后的值强制刷回主内存,而不是仅仅更新线程的本地缓存。补充:
volatile
的主要作用是保证共享变量的可见性和有序性。共享变量是指在多个线程之间共享的变量,例如单例模式中的 instance
变量。如果不使用volatile
关键字修饰 instance
变量,在多线程环境下可能会出现空指针异常等问题。
这是因为当一个线程修改了 instance
变量的值时,其他线程可能无法立即看到修改后的值,从而出现空指针异常等问题。
使用 volatile
关键字可以解决这个问题,因为它可以保证对共享变量的修改对其他线程是可见的。
除了可见性和有序性之外,volatile 还可以防止指令重排序。指令重排序是指 CPU 为了提高程序执行的效率而对指令执行的顺序进行调整的行为。在单例模式中,如果 instance 变量没有被声明为 volatile,那么在多线程环境下可能会出现单例对象被重复创建的问题。这是因为在多线程环境下,某些线程可能会在 instance 变量被初始化之前就调用
getInstance()
方法,从而导致多次创建单例对象。通过将 instance 变量声明为 volatile,可以保证在创建单例对象之前,instance 变量已经被正确地初始化了。
/** * 提供一个静态的公有方法,加入双重检查代码,解决线程安全问题,同时解决懒加载问题 * 即双重检查锁模式 * * @return instance(单例对象) */public static DoubleLockStyle getInstance() { if (instance == null) { // 同步代码块,线程安全的创建实例 synchronized (DoubleLockStyle.class) { //之所以要再次判断,是因为可能有多个线程同时进入了第一个if判断 if (instance == null) { instance = new DoubleLockStyle(); } } } return instance;}
在获取方法中,使用synchronized
来同步,使它线程安全。
双重锁模式是一种用于延迟初始化的优化模式,在第一次调用时创建单例对象,并在之后的访问中直接返回该对象。它通过使用双重检查锁定(double checked locking)来保证在多线程环境下只有一个线程可以创建单例对象,并且不会加锁影响程序性能。
优点:
线程安全:使用双重锁模式可以保证在多线程环境下只有一个线程可以创建单例对象,并且不会加锁影响程序性能。延迟初始化:在第一次调用时创建单例对象,可以避免不必要的资源浪费和内存占用。性能优化:通过使用双重检查锁定,可以避免不必要的锁竞争,从而提高程序性能。缺点:
实现复杂:双重锁模式的实现相对复杂,需要考虑线程安全和性能等因素,容易出现错误。可读性差:由于双重锁模式的实现比较复杂,代码可读性较差,不易于理解和维护。难以调试:由于双重锁模式涉及到多线程并发访问,因此在调试过程中可能会出现一些难以定位和复现的问题。在双重锁模式中,确实只有一个 synchronized
关键字,但是这个 synchronized
关键字是在代码中被使用了两次,因此被称为“双重锁”。
具体来说,双重锁模式通常会在 getInstance
方法中使用 synchronized
关键字来保证线程安全,但是这会影响程序的性能,因为每次访问 getInstance
方法都需要获取锁。为了避免这个问题,双重锁模式使用了一个优化技巧,即只有在第一次调用 getInstance
方法时才会获取锁并创建单例对象,以后的调用都直接返回已经创建好的单例对象,不需要再获取锁。
具体实现时,双重锁模式会在第一次调用 getInstance
方法时进行两次检查,分别使用外部的 if
语句和内部的 synchronized
关键字。外部的 if
语句用于判断单例对象是否已经被创建,如果已经被创建则直接返回单例对象,否则进入内部的 synchronized
关键字块,再次检查单例对象是否已经被创建,如果没有被创建则创建单例对象并返回,否则直接返回已经创建好的单例对象。
这样做的好处是,在多线程环境下,只有一个线程可以进入内部的 synchronized
关键字块,从而保证了线程安全,同时避免了每次访问 getInstance
方法都需要获取锁的性能问题。
因为已经熟悉了这个设计模式原理,我就直接放代码了。
public class StaticInnerClassStyle { /** * 私有化构造方法(防止外部new新的对象) */ private StaticInnerClassStyle() { } /** * 静态内部类 */ private static class SingletonInstance { // 静态内部类中的静态变量(单例对象) private static final StaticInnerClassStyle INSTANCE = new StaticInnerClassStyle(); } /** * 提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE * * @return instance(单例对象) */ public static StaticInnerClassStyle getInstance() { return SingletonInstance.INSTANCE; }}
优点:
线程安全:静态内部类在第一次使用时才会被加载,因此在多线程环境下也可以保证只有一个线程创建单例对象,避免了线程安全问题。延迟加载:静态内部类模式可以实现延迟加载,即只有在第一次调用getInstance
方法时才会加载内部类并创建单例对象,避免了在程序启动时就创建单例对象的开销。缺点:
需要额外的类:静态内部类模式需要定义一个额外的类来实现单例模式,如果项目中有大量的单例对象,则会增加代码量。无法传递参数:静态内部类模式无法接受参数,因此无法在创建单例对象时传递参数,这可能会对某些场景造成限制。总的来说,静态内部类模式是一种性能高、线程安全的单例模式实现方式,适用于大部分场景。
如果需要传递参数或者需要频繁创建单例对象,则可能需要考虑其他的实现方式。
懒加载即延时加载 --> 使用时采取创建对象。
在静态内部类模式中,单例对象是在静态内部类中被创建的。静态内部类只有在第一次被使用时才会被加载,因此单例对象也是在第一次使用时被创建的。这样就实现了延迟加载的效果,即在需要时才创建单例对象,避免了在程序启动时就创建单例对象的开销。
此外,静态内部类中的静态变量和静态方法是在类加载时被初始化的,而静态内部类本身是非常轻量级的,加载和初始化的时间和开销都非常小。因此,静态内部类模式既能够实现懒加载,又不会带来太大的性能损失。
总之,它在静态初始化意料之外,我相信也在你意料之外。
/** * @author JanYork * @date 2023/3/1 17:54 * @description 设计模式之单例模式(枚举单例) * 优点:避免序列化和反序列化攻击破坏单例,避免反射攻击破坏单例(枚举类型构造函数是私有的),线程安全,延迟加载,效率较高。 * 缺点:代码复杂度较高。 */public enum EnumerateSingletons { /** * 枚举单例 */ INSTANCE; public void whateverMethod() { // TODO:do something ,在这里实现单例对象的功能 }}
在上述代码中,INSTANCE
是 EnumSingleton
类型的一个枚举常量,表示单例对象的一个实例。由于枚举类型的特性,INSTANCE
会被自动初始化为单例对象的一个实例,并且保证在整个应用程序的生命周期中只有一个实例。
使用枚举单例的方式非常简单,只需要通过 EnumSingleton.INSTANCE
的方式来获取单例对象即可。例如:
EnumerateSingletons singleton = EnumerateSingletons.INSTANCE;singleton.doSomething();
使用枚举单例的好处在于,它是线程安全、序列化安全、反射安全的,而且代码简洁明了,不容易出错。另外,枚举单例还可以通过枚举类型的特性来添加其他方法和属性,非常灵活。
枚举单例的缺点相对来说比较少,但是也存在一些限制:
不支持懒加载:枚举类型的实例创建是在类加载的时候完成的,因此无法实现懒加载的效果。无法继承:枚举类型不能被继承,因此无法通过继承来扩展单例类的功能。有些情况下不太方便使用:例如需要传递参数来创建单例对象的场景,使用枚举单例可能不太方便。总之,枚举单例是一种非常优秀的单例实现方式,它具有线程安全、序列化安全、反射安全等优点,适用于大多数单例场景,但也存在一些限制和局限性。需要根据具体的场景来选择合适的单例实现方式。
设计模式本就是业务中优化一些设计带来的概念性设计,我们需要结合业务分析:
饿汉式:适用于单例对象较小、创建成本低、不需要懒加载的场景。懒汉式:双重锁:适用于多线程环境,对性能要求较高的场景。静态内部类:适用于多线程环境,对性能要求较高的场景。枚举:适用于单例对象创建成本较高,且需要考虑线程安全、序列化安全、反射安全等问题的场景。如果你的单例对象创建成本低、不需要考虑线程安全、序列化安全、反射安全等问题,建议使用饿汉式实现单例;如果需要考虑线程安全和性能问题,可以选择懒汉式的双重锁或静态内部类实现方式;如果需要考虑单例对象创建成本较高,需要考虑线程安全、序列化安全、反射安全等问题,建议选择枚举单例实现方式。当然,在实际的开发中,还需要考虑其他一些因素,如单例对象的生命周期、多线程访问情况、性能要求、并发访问压力等等,才能综合选择最合适的单例实现方式。
来自某AI(敏感词):
标签:
最新推荐
大家好,我是小简,这一篇文章,6种单例方法一网打尽,虽然单例模式很简单,但是也是设计模式入门基础,...
甘肃白银启动“无废城市”建设黄河沿岸遍地成“景”---图为白银市美丽乡村花海。甘肃省白银市生态环境局...
据中央纪委国家监委网站3月17日消息,河南省农村信用社联合社党委委员、副主任吴金鹏涉嫌严重违纪违法,...
航天发展(000547)03月17日在投资者关系平台上答复了投资者关心的问题。
小手牵大手作文初二第1篇我的小手真棒,你可别小看哦,你想知道吗?那我们就一起走进我的小手吧。记得有...
cp:宋岚x薛洋有聂瑶曦桑忘羡等。年龄操作,现代设定,娱乐圈反 包 养 长篇,慢热,ooc--------------...
工业旅游兴起,一线工人“唱主角”(主题)工人日报-中工网记者王晓颖通讯员罗霞段文海阅读提示伴随着全...
1、总点击:1166106月点击:413111周点击:127853小说类别:时空穿梭总推荐:31595
双喜临门!伊万-托尼27岁生日当天重返英格兰队大名单,英超,总冠军,英格兰队,德国足球,足球竞赛,布伦特福...
奥斯梅恩:自信是最强前锋之一,德罗巴是我的偶像,那不勒斯,我的偶像,法兰克福,德国足球,巴西足球,沃尔...
汽车现在已经越来越普及,基本上都快实现每家每户都有汽车了,那么汽车这么多的情况之下,我们在用车的...
昆明信息港讯记者冯垚3月14日,记者在昆明市呈贡区老年大学了解到,该校于3月6日正式开学,在呈贡46个社...
随着全球对环保意识的不断提高,电动车市场迅猛发展。奥迪Q5e-tron(图片|配置|询价)40e-tron是一款高端...
据文化和旅游部消息,3月15日起,试点恢复全国旅行社及在线旅游企业经营中国公民赴有关国家(第二批)出...
1、孩子咬指甲的原因主要有以下几种情况:1。2、缺乏微量元素,如缺铁、缺锌等,会引起吸吮、咬指甲。3...
*ST凯乐1月12日公告,公司收到公司控股股东荆州市科达商贸有限公司通知,科达商贸持有的公司股票被动减...
3月15日北向资金增持81 6万股歌华有线。近5个交易日中,获北向资金增持的有3天,累计净增持178 7万股...
国内基建开工率回升,行业龙头中国铁建创两年来新高。3月15日,科技类题材偃旗息鼓,CPO概念、信息安全...
1、在360上面找车辆违章查询。2、进去后右边有查询车辆填充的地!填完后在中间出来相对项目!在上面输入...
1、中国校友会网(cuaa net)又称中国校友网,是中国专业为校友会组织提供网络服务的网站,创建于2001年11月。2
1、报纸刊登过《军队转业干部住房保障办法》本人记不清楚。2、财基字[1978]182号和国转字[1978]2号文件有相关
女演员实名举报五星级酒店,涉事酒店回应
又是一年春好处,植树造林正当时,在全国第45个义务植树节即将来临之际,3月10日,连云港民建东部城区总...
一、题文边快广养半件义布因红还眼写出下列加点词语的反义词。边快广养半件义布因红还眼①两个人勤劳节...
每经AI快讯,有投资者在投资者互动平台提问:尊敬的董秘,贵公司有跟中国电信,中国移动合作吗?洪涛股...
3月14日,富国远见优选混合A最新单位净值为1 0117元,累计净值为1 0117元,较前一交易日下跌0 51%。...
受冷空气大风影响,预计3月14日20时至15日20时,新疆南部、甘肃西部、内蒙古中部和东南部、辽宁西部、河...
1、截面尺寸为80mm*60mm*4mm的铝合金方管的重量可以这样计算,其他截面尺寸类似。2、1m长的方管的体积 V=表
深交所3月14日下发关于对鸿达兴业的监管函。监管函指出,2023年2月24日,公司披露《关于深交所对公司问...
出自DSmile老师原设的人气恋爱喜剧AVG《一生推不如一生恋》中的主角——「速星爱来」、「古馆恋」手办即...
对于患有心血管疾病的人来说,远程医疗是一种经过验证且有价值的选择;然而,根据今天发表在《循环》杂志...
在这样的情况下,他们在主场占尽优势的情况下,都没有能够击败保级球队萨勒尼塔纳,错失了积分追平同城...
1、MEI自己根据实际情况来写吧,主要写一下主要的工作内容,如何努力工作,取得的成绩,最后提出一些合...
1、这个是技术学院嘛?还行,在当地还是不错的就业,这个是很有保证的。2、一般情况下,这些都是与社会...
1、盒式磁带录音机(,也称为卡式录音机,是指使用盒式录音带进行录音、重放的录音机,磁带带宽为3 81毫...
1、2万应该足够`要看场面`就是店面`如果你是大型的话水果种类多`45个平方的面积要十多万的投入。2、还要...
乌鲁木齐商品房维修资金3月13日起交存凭据启用电子票据,维修,上交,交存
3月13日11点28分,国产软件板块指数报2608 807点,涨幅达2%,成交469 15亿元,换手率2 32%。板块个股...
新华社首尔3月12日电(记者陆睿、孙一然)2023年短道速滑世锦赛12日展开最后一个比赛日的角逐,中国队摘...
全球财经日志|2023年3月13日
A股市场持续震荡之际,外资机构又出手加仓。近期,A股市场在3200点至3300点之间持续震荡,北向资金1月创...
一、没字多音字组词的近义词1、有[yǒu]2、出[chū]3、浮[fú]二、没字多音字组词的反义词4、
03月12日12时云南昭通疫情数据阳了以后为什么会腰疼?应该怎么办?以下为详情!一、03月12日12时昭通疫...
1、截止到2019年5月《烟花易冷》没有被禁。2、《烟花易冷》是北京剧角映画文化传媒有限公司、海宁剧制文...
8月份,一块办公、学习、娱乐都能用的米家液晶小黑板在小米商城开启众筹,仅1小时41分钟,众筹数量突破2...
1、弗洛伊德的名言笑话给予我们快感,是通过把一个充满能量和紧张度的有意识过程转化为一个轻松的无意识...
1、用心做事的人需要坚定的理想,这个的核心是信念。2、用脑做事的人需要科学的方法,这个的核心是思维...
新华社北京3月10日电(记者姚均芳、吴雨)中国人民银行10日发布金融统计数据显示,2023年2月份我国人民...
1、韩泰就是韩泰轮胎。2、韩泰轮胎常见的有四个系列,分别是维恩托斯万途仕、OptimoAotema、Enfren
1、中老年钙片新盖中盖比较好,推荐使用。2、我国营养学会制定的指南要求人体每日摄入大约800mg的钙元素...
一张陌生人的图片“活化”成为视频? 深度合成正瓦解“眼见为实”
一张陌生人的图片“活化”成为视频? 深度合成正瓦解“眼见为实”
迅捷微信聊天恢复软件_如何通过迅捷微信聊天记录恢复器恢复微信聊天记录
云南省导游协会、云南省旅行社协会发布《致广大导游和游客朋友的一封信》 天天视点
天天短讯!15.2摄氏度!格陵兰岛3月异常高温创同期最高纪录
刘雯井柏然、桂纶镁昆凌,CHANEL秀上的CP真好磕! 聚看点
天天关注:当日快讯:叙利亚总统阿萨德会见到访的伊朗外长阿卜杜拉希扬
爱心人士反映四川江油流浪动物救助站动物生存环境恶劣 警方:展开调查
香港科技探索公布2月平均每日订单总商品交易额2220万港元-天天动态
世界快资讯:catia装配导入零件怎么移动_catia装配导入零件
张扬两会访谈|中国女足主教练水庆霞:任何事如果轻而易举得到,那就不叫奋斗
今日热议:北京动物园将派兽医和饲养员下周抵美 护理并护送“丫丫”回国
世界今日报丨中山职业技术学院宿舍六人床多长_中山职业技术学院宿舍
ChatPDF也来了!一键上传文件即可解读,复制粘贴都省了-每日热讯
科蓝软件:已有多个数字乡村业务案例 并已荣获2022数字普惠金融服务乡村振兴成果奖 焦点热门
齐齐哈尔新型冠状病毒肺炎疫情:3月7日齐齐哈尔疫情最新消息今天数据统计情况通报-环球速看料
Copyright © 2015-2022 南方律师网版权所有 备案号:粤ICP备18023326号-21 联系邮箱:855 729 8@qq.com