前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2018 05 09

2018 05 09

原创
作者头像
用户2145987
发布2018-05-09 13:54:02
7594
发布2018-05-09 13:54:02
举报
文章被收录于专栏:易视终端

单例模式:

顾名思义就是只能有一个,不能在出现第二个。就如同地球上没有两片完全一模一样的树叶一样。

程序猿的角度理解:一个类有且只能有一个实例,不能出现第二个,并且整个项目系统中都能访问该实例。

面试官:为啥不能出现第二个?

程序猿:。。。(这个面试官是笨蛋,出现第二个那就不叫单例模式了,那至少得叫双例模式,是吧?)

面试官:为啥整个项目系统中都能访问该实例?

程序猿:不能访问该实例,那new出来还有什么意义。

面试官:那你给我写个单例模式吧

程序猿:写就写,这能难倒我,哼,先写个懒汉式单例(第一种

[java] view plain copy

  1. package com.tang.study.singleton;  
  2. /**
  3.  * 单例模式
  4.  * 懒汉式单例
  5.  * Created by tgp on 2018/4/15.
  6.  */
  7. public class SingletonPatternOne {  
  8. //关键点0:构造函数是私有的
  9. private SingletonPatternOne(){}  
  10. ///关键点1:声明单例对象是静态的
  11. private static SingletonPatternOne instance  = null;  
  12. //通过静态方法来构造对象
  13. public static SingletonPatternOne getInstance(){  
  14. if(instance == null){//关键点2:判断单例对象是否已经被构造
  15.             instance = new SingletonPatternOne();  
  16.         }  
  17. return instance;  
  18.     }  
  19. public void showMessage(){  
  20.         System.out.println("懒汉式单例:啥时候用啥时候NEW。");  
  21.     }  
  22. }  

面试官:你这代码遇到多线程的并发条件下就不安全了吧。在if判断那里,如果两个线程同时访问,有可能给new出多个单例实例,都多个了,还是屁的“单例”啊。

程序猿:(额,好像也是,幸亏我还有点干货,再撸一段),那我给您再写一段(第二种

[java] view plain copy

  1. /**
  2.  * 单例模式
  3.  * 饿汉式单例
  4.  * Created by tgp on 2018/4/15.
  5.  */
  6. public class SingletonPatternTwo {  
  7. //关键点0:构造函数是私有的
  8. private SingletonPatternTwo(){  
  9.     }  
  10. ///关键点1:声明单例对象是静态的
  11. private static SingletonPatternTwo instance  = new SingletonPatternTwo();  
  12. //通过静态方法来构造对象
  13. public static SingletonPatternTwo getInstance(){  
  14. return  instance;  
  15.     }  
  16. public void showMessage(){  
  17.         System.out.println("饿汉式单例:管你用不用,我都先给你new出来,用不用是你的事,一劳永逸,省的你每次用时都来烦我。");  
  18.     }  

面试官:那你给我讲讲你写的这种单例模式的优缺点

程序猿:

   优点:这种写法在类加载的时候就完成对象的实例化,避免了线程不安全的问题。

   缺点:在类加载的时候就完成了实例化,如果这个类一直没用,就会造成内存的浪费。

面试官:这种方式是解决了线程不安全的问题,但内存浪费总是不太好吧,尤其是服务器的内存都是很贵的

程序猿:好吧,那我给您优化优化(第三种

[java] view plain copy

  1. public class SingletonPatternThree {  
  2. //关键点0:构造函数是私有的
  3. private SingletonPatternThree(){}  
  4. ///关键点1:声明单例对象是静态的
  5. private static SingletonPatternThree instance  = null;  
  6. //通过静态方法来构造对象
  7. public static synchronized SingletonPatternThree getInstance(){  
  8. if(instance == null){//关键点2:判断单例对象是否已经被构造
  9.             instance = new SingletonPatternThree();  
  10.         }  
  11. return instance;  
  12.     }  
  13. public void showMessage(){  
  14.         System.out.println("懒汉式加锁:第一次调用才初始化,避免内存浪费,同时线程安全");  
  15.     }  
  16. }  

面试官:内存浪费和线程安全的问题都解决了,那方法加锁会影响效率,多线程的情况,第一个访问方法期间,其它用户只能等待,用户体验太差

程序猿:(有完没完了。。)逼我放大招(第四种:双重检查)

[java] view plain copy

  1. //通过静态方法来构造对象
  2. public static SingletonPatternFour getInstance(){  
  3. if(instance == null){//关键点2:判断单例对象是否已经被构造
  4. synchronized(SingletonPatternFour.class){//关键点3:加锁
  5. if(instance == null){//关键点4:二次判断单例是否已经被构造
  6.                    instance = new SingletonPatternFour();  
  7.                }  
  8.            }  
  9.        }  
  10. return instance;  
  11.    }  
  12. public void showMessage(){  
  13.        System.out.println("进行了两次if (instance == null)检查,这样就可以保证线程安全了。" +  
  14. "这样,实例化代码只用执行一次,后面再次访问时,判断if (instance == null),直接return实例化对象。");  
  15.    }  

面试官:这种不错,那你还会其它的实现方法吗?

程序猿:(我会的可多了,都拿出来怕吓着你)我还会几种别的(第五种:静态内部类)

[java] view plain copy

  1. public class Singleton {  
  2. private Singleton() {}  
  3. private static class SingletonInstance {  
  4. private static final Singleton INSTANCE = new Singleton();  
  5.     }  
  6. public static Singleton getInstance() {  
  7. return SingletonInstance.INSTANCE;  
  8.     }  
  9. }  

程序猿:类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。

优点:避免了线程不安全,延迟加载,效率高。

第六种:枚举)

[java] view plain copy

  1. public enum Singleton {    
  2.     INSTANCE;    
  3. public void whateverMethod() {    
  4.     }    
  5. }   

经验之谈:一般情况下,推荐双检锁方式和静态内部类。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档