单例模式代码_设计模式之单例:程序员必知必会,举例子+代码示例,通俗易懂...
推荐学习
- 给力!啃烂这套“核心知识”+“高级面试”,成功定级腾讯JavaT4
举个通俗的例子:我们电脑桌面上的一些软件快捷方式,我们可以创建多个这样的快捷方式,但是它们都是同一个,也就是说我们运行软件只有一个,其他地方只是引用这一个实例。
好了,有了例子打底后,我们来看看通常情况下new实例化会创建新的一个对象,那么同理,new多个时也会创建多个新的对象。打印它的hashCode(相等的对象必须有相等的散列码即hashCode),会发现下面的hashCode不相同。
代码实例
class Singleton1{ Singleton1(){}}public class demo1 { public static void main(String[] args) { System.out.println(new Singleton1().hashCode()); System.out.println(new Singleton1().hashCode()); }}
运行结果
接下来我们来解决一下上面出现的问题,实现单例模式,单例模式又分为两种,一种是比较简单的饿汉式和问题比较多的懒汉式。
饿汉式
(饿汉式顾名思义,很冲动,一上来就开干)
可以看到代码的一个关键点:用private声明了构造方法,这样做其他类就不能直接通过new实例化了,我们知道一旦用private封装,就需要用get方式获取(搞这么多事情,其实就是为了由该类创建自己唯一的一个对象,然后不管后面多少类需要用到它,都杜绝了用new开辟新的实例浪费内存空间,通通都得用它这个唯一的,通过它的类然后调用get方法获取,这样保证全局的唯一性)
class Singleton2{ private static final Singleton2 singleton = new Singleton2(); private Singleton2(){} public static Singleton2 getSingleton(){ return singleton; }}
测试(可以看到相同的HashCode)
public class demo2 { public static void main(String[] args) { System.out.println( Singleton2.getSingleton().hashCode()); System.out.println( Singleton2.getSingleton().hashCode()); }}
运行结果
上面的饿汉式实现了我们的单例模式,多线程下它是安全的,但是可以发现不管你有没有用到它,它都会一上来就建好给你,(类加载时就初始化)这样就会浪费了内存空间。
懒汉式
(懒汉式正好和饿汉式相反,没有饿汉式的冲动,有点懒,问题也多)
我们可以比较着来学,看懒汉式和饿汉式的它们的相同点和不同点,先看相同点:不管是懒汉式和饿汉式都有一个关键的代码是一样的,就是:私有化构造方法(这里你还问为什么的话,看上面饿汉式那里有解释),不同点是:没有一上来就new,而是在get方法里多了一个判断,如果还没实例化那么就实例化一个,如果实例化了,返回这个实例化好的。
详细看代码示例
class Singleton{ private Singleton(){} private static Singleton instance; public static Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; }}public class demo3 { public static void main(String[] args) { System.out.println(Singleton.getInstance().hashCode()); System.out.println(Singleton.getInstance().hashCode()); }}
运行结果
可以看到现在懒汉式实现了单例模式,第一次调用才初始化,避免内存浪费,但是上面说了,懒汉式是有问题的,它多线程下是不同步的。我们来测试一下懒汉式多线程情况下
class Singleton{ private Singleton(){ System.out.println(Thread.currentThread().getName()); } private static Singleton instance; public static Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; }}public class demo3 { public static void main(String[] args) { //多线程下 for(int i = 0;i<10;i++){ new Thread(new Runnable(){ @Override public void run() { Singleton.getInstance(); } }).start(); } }}
运行结果(结果是不一致)
那么怎么解决呢?用双检锁/双重校验锁(也称DCL)(你可能会疑问了,为什么不直接在get方法上加synchronized不也可以吗,是可以的,但是会影响性能,因为我们的目的只是针对实例执行一次这个关键的代码才需要同步,所以用双检锁可以安全且在多线程情况下保持高性能)
双检锁的代码示例,你可能还有一个疑问,为什么加上volatile关键字,有什么用呢?可以这么理解,用volatile解决指令重排的问题,因为new的时候不是原子性(什么是原子性很好理解,要么完整的执行,要么就完全的不执行,这是它的一个特性),我们创建的时候会经过这么一个过程,1.分配内存空间、2.执行构造方法,对象初始化、3.指针指向这个内存空间。正常情况一个线程是按着顺序123走的,但是当两个或多个线程出现,它就不一定会按着顺序来,那么就会出现一个指令重排的问题。(所以简单的理解volatile就是用来避免指令重排,不按顺序来)
class Singleton{ private Singleton(){ System.out.println(Thread.currentThread().getName()); } private volatile static Singleton instance; public static Singleton getInstance(){ if(instance == null){ synchronized (Singleton.class){ if (instance == null){ instance = new Singleton(); } } } return instance; }}public class demo3 { public static void main(String[] args) { //多线程下 for(int i = 0;i<100;i++){ new Thread(new Runnable(){ @Override public void run() { Singleton.getInstance(); Singleton.getInstance(); } }).start(); } }}
运行结果(多次运行结果一致)
作者:一颗彪悍的种子
原文链接:https://blog.csdn.net/A_hxy/article/details/106142617
单例模式代码_设计模式之单例:程序员必知必会,举例子+代码示例,通俗易懂...相关推荐
- 让电脑崩溃的java代码_这些都是让程序员崩溃的瞬间...
作者:五月的仓颉原文:cnblogs.com/xrq730/p/4865416.html来源:博客园 我认为,代码优化的最重要的作用应该是:避免未知的错误.在代码上线运行的过程中,往往会出现很多我们意 ...
- java程序员拜年代码_作为一个资深的程序员我们应该这么拜年
作为一个资深的程序员我们应该这么拜年,瞬间高大上! C:printf("祝大家新年快乐"); C++ : cout< QBasic : Print "祝大家新年快乐 ...
- java里用set写自我介绍代码_【优质】java程序员自我介绍-优秀word范文 (8页)
本文部分内容来自网络整理,本司不为其真实性负责,如有异议或侵权请及时联系,本司将立即删除! == 本文为word格式,下载后可方便编辑和修改! == java程序员自我介绍 第1篇第2篇第3篇第4篇第 ...
- 程序员应知必会的思维模型之 7 邓巴数字 (Dunbar‘s Number)
邓巴数字 (Dunbar's Number) 邓巴数字是对一个人能够保持稳定社会关系的人数的认知极限--在这种关系中,一个人知道每个人是谁,也知道每个人与其他人的关系如何.而对这一数字的确切值则有着一 ...
- 程序员应知必会的思维模型之 3 破窗效应 (The Broken Windows Theory)
破窗效应 (The Broken Windows Theory) 在破窗理论中认为,一些明显的犯罪迹象(或缺乏环保意识)会导致进一步的.更严重的犯罪(或环境的进一步恶化). 软件领域应用 破窗理论已应 ...
- 程序员应知必会的思维模型之 18 林纳斯定律 (Linus‘s Law)
林纳斯定律 (Linus's Law) 足够多的眼睛,就可让所有问题浮现.–Eric S. Raymond 简单地说,能够看到问题的人越多,有人解决过相关的问题或事情的可能性就越高. 最初该定律是用来 ...
- 程序员应知必会的思维模型之 25 普特定律 (Putt‘s Law)
普特定律 (Putt's Law) 技术由两类人主导,一类是纯粹的管理人员, 一类是纯粹的技术人员. 普特定律常常遵循普特推论: 每一个技术层次,假以时日,能力将逆转. 这些结论表明,由于各种选择标准 ...
- 程序员应知必会的思维模型之 19 梅特卡夫定律 (Metcalfe‘s Law)
梅特卡夫定律 (Metcalfe's Law) 在网络理论中,系统的价值约等于系统用户数的平方. 这个定律基于一个系统中可能的连接对数量,并且与里德定律 (Reed's Law) 十分相近.奥德利兹科 ...
- 程序员应知必会的思维模型之 15 技术成熟度曲线 (The Hype Cycle or Amara‘s Law)
技术成熟度曲线 (The Hype Cycle or Amara's Law) 我们倾向于过高估计技术在短期内的影响,并低估长期效应.–罗伊·阿马拉 (Roy Amara) 技术成熟度曲线是高德纳咨询 ...
最新文章
- 生产企业开具加工费发票的问题
- java重载_Java的重载与覆盖,傻傻分不清!
- leetcode - Missing Ranges
- 关于jquery与dom元素转换
- OS X开发:NSProgressIndicator进度指示器控件
- 你没有见过的 7 种 for 循环优化,超好用!
- [蓝桥杯]2019年第十届省赛真题C/C++ B组 填空+大题
- 英语阅读理解关于计算机,一篇摘选的关于计算机的英语阅读材料,对大家的英语也许会有提高!...
- 华为P50系列终于要来了!但最大问题却是...
- 归心似箭,IT达人分享抢票攻略
- oracle libary cache 命中率
- [Luogu P2893][USACO08FEB]修路Making the Grade
- FastStone Capture:Windows系统下小巧好用的宝藏电脑截图软件
- ov5640帧率配置_基于OV5640的FPGARAM HDMI显示
- ios 图片简单360度旋转动画
- JAVA|什么是Sdkman
- OSAL 之功耗管理
- 9、使用容器数据卷部署MySQL
- 母牛问题。母牛每年生一只母牛,新出生的母牛成长三年后也能每年生一只 母牛……
- 自助建站:凡科建站和PageAdmin建站系统的比较
热门文章
- 用计算机解决自动驾驶,自动驾驶汽车很美好,但这3个逻辑解决不了,依然是人类驾驶汽车...
- android 7.0 黑屏,Android app启动是出现白屏或者黑屏如何解决?
- itextpdf添加表格元素_itext生成pdf文件-表格
- c json保存整型数组_命令行JSON解析神器jq
- jsoup爬虫,爬取全站代码
- 开源java项目_请问有哪些开源java项目值得学习的?学习完了容易找工作的?
- 计算机会计简要回答会计电算化的作用,会计电算化在学校财务管理中的作用
- php 3d animation,如何用HTML5的Canvas制作3D动画效果
- SpringBoot-(1)-IDEA创建SpringBoot项目并运行访问接口
- 元素位置及宽度的计算总节