推荐学习

  • 给力!啃烂这套“核心知识”+“高级面试”,成功定级腾讯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

单例模式代码_设计模式之单例:程序员必知必会,举例子+代码示例,通俗易懂...相关推荐

  1. 让电脑崩溃的java代码_这些都是让程序员崩溃的瞬间...

    作者:五月的仓颉原文:cnblogs.com/xrq730/p/4865416.html来源:博客园 我认为,代码优化的最重要的作用应该是:避免未知的错误.在代码上线运行的过程中,往往会出现很多我们意 ...

  2. java程序员拜年代码_作为一个资深的程序员我们应该这么拜年

    作为一个资深的程序员我们应该这么拜年,瞬间高大上! C:printf("祝大家新年快乐"); C++ : cout< QBasic : Print "祝大家新年快乐 ...

  3. java里用set写自我介绍代码_【优质】java程序员自我介绍-优秀word范文 (8页)

    本文部分内容来自网络整理,本司不为其真实性负责,如有异议或侵权请及时联系,本司将立即删除! == 本文为word格式,下载后可方便编辑和修改! == java程序员自我介绍 第1篇第2篇第3篇第4篇第 ...

  4. 程序员应知必会的思维模型之 7 邓巴数字 (Dunbar‘s Number)

    邓巴数字 (Dunbar's Number) 邓巴数字是对一个人能够保持稳定社会关系的人数的认知极限--在这种关系中,一个人知道每个人是谁,也知道每个人与其他人的关系如何.而对这一数字的确切值则有着一 ...

  5. 程序员应知必会的思维模型之 3 破窗效应 (The Broken Windows Theory)

    破窗效应 (The Broken Windows Theory) 在破窗理论中认为,一些明显的犯罪迹象(或缺乏环保意识)会导致进一步的.更严重的犯罪(或环境的进一步恶化). 软件领域应用 破窗理论已应 ...

  6. 程序员应知必会的思维模型之 18 林纳斯定律 (Linus‘s Law)

    林纳斯定律 (Linus's Law) 足够多的眼睛,就可让所有问题浮现.–Eric S. Raymond 简单地说,能够看到问题的人越多,有人解决过相关的问题或事情的可能性就越高. 最初该定律是用来 ...

  7. 程序员应知必会的思维模型之 25 普特定律 (Putt‘s Law)

    普特定律 (Putt's Law) 技术由两类人主导,一类是纯粹的管理人员, 一类是纯粹的技术人员. 普特定律常常遵循普特推论: 每一个技术层次,假以时日,能力将逆转. 这些结论表明,由于各种选择标准 ...

  8. 程序员应知必会的思维模型之 19 梅特卡夫定律 (Metcalfe‘s Law)

    梅特卡夫定律 (Metcalfe's Law) 在网络理论中,系统的价值约等于系统用户数的平方. 这个定律基于一个系统中可能的连接对数量,并且与里德定律 (Reed's Law) 十分相近.奥德利兹科 ...

  9. 程序员应知必会的思维模型之 15 技术成熟度曲线 (The Hype Cycle or Amara‘s Law)

    技术成熟度曲线 (The Hype Cycle or Amara's Law) 我们倾向于过高估计技术在短期内的影响,并低估长期效应.–罗伊·阿马拉 (Roy Amara) 技术成熟度曲线是高德纳咨询 ...

最新文章

  1. 生产企业开具加工费发票的问题
  2. java重载_Java的重载与覆盖,傻傻分不清!
  3. leetcode - Missing Ranges
  4. 关于jquery与dom元素转换
  5. OS X开发:NSProgressIndicator进度指示器控件
  6. 你没有见过的 7 种 for 循环优化,超好用!
  7. [蓝桥杯]2019年第十届省赛真题C/C++ B组 填空+大题
  8. 英语阅读理解关于计算机,一篇摘选的关于计算机的英语阅读材料,对大家的英语也许会有提高!...
  9. 华为P50系列终于要来了!但最大问题却是...
  10. 归心似箭,IT达人分享抢票攻略
  11. oracle libary cache 命中率
  12. [Luogu P2893][USACO08FEB]修路Making the Grade
  13. FastStone Capture:Windows系统下小巧好用的宝藏电脑截图软件
  14. ov5640帧率配置_基于OV5640的FPGARAM HDMI显示
  15. ios 图片简单360度旋转动画
  16. JAVA|什么是Sdkman
  17. OSAL 之功耗管理
  18. 9、使用容器数据卷部署MySQL
  19. 母牛问题。母牛每年生一只母牛,新出生的母牛成长三年后也能每年生一只 母牛……
  20. 自助建站:凡科建站和PageAdmin建站系统的比较

热门文章

  1. 用计算机解决自动驾驶,自动驾驶汽车很美好,但这3个逻辑解决不了,依然是人类驾驶汽车...
  2. android 7.0 黑屏,Android app启动是出现白屏或者黑屏如何解决?
  3. itextpdf添加表格元素_itext生成pdf文件-表格
  4. c json保存整型数组_命令行JSON解析神器jq
  5. jsoup爬虫,爬取全站代码
  6. 开源java项目_请问有哪些开源java项目值得学习的?学习完了容易找工作的?
  7. 计算机会计简要回答会计电算化的作用,会计电算化在学校财务管理中的作用
  8. php 3d animation,如何用HTML5的Canvas制作3D动画效果
  9. SpringBoot-(1)-IDEA创建SpringBoot项目并运行访问接口
  10. 元素位置及宽度的计算总节