A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

单例设计模式为什么推荐使用饿汉式呢?我总觉得懒汉式比较好呢?求解其中原因。

7 个回复

正序浏览
延迟加载,启动的时候不会创建对象
回复 使用道具 举报
不要着急 你还没学到多线程吧?  学了多线程就有详细的介绍  但是这个单例设计模式的设计思想你还是要好好理解一下的!
回复 使用道具 举报
两大原因:代码简单,线程安全
回复 使用道具 举报
fei_xiong 发表于 2014-5-2 09:30
而且如果懒汉式要想安全的话,需要加同步,但加上同步之后,效率会变低,为了解决效率变低的问题需要进行 ...

谢谢。明白了。
回复 使用道具 举报
  1. 先写一个简单的懒汉式:

  2. public class Singleton
  3. {
  4.         private static Singleton instance = null;
  5.         private Singleton() {}

  6.         public static synchronized Singleton getInstance()
  7.         {
  8.                 if(instance == null)
  9.                 {
  10.                         instance = new Singleton();
  11.                 }
  12.                 return instance;
  13.         }
  14. }

  15. 显然在多线程下肯定是不安全的,故加上synchronized,这样做封锁的是整个对象,性能会降低,
  16. 因为每次调用getInstance()时都要对对象上锁,事实上只要在第一次调用时会创建对象,以后就不用创建了。
  17. 改进如下:

  18. public class Singleton
  19. {
  20.         private static Singleton instance = null;
  21.         private Singleton() {}

  22.         public static Singleton getInstance()
  23.         {
  24.                 if(instance == null)
  25.                 {
  26.                         synchronized(this)
  27.                         {
  28.                                 if(instance == null)
  29.                                 {
  30.                                         instance = new Singleton();
  31.                                 }
  32.                         }
  33.                 }
  34.                 return instance;
  35.         }
  36. }

  37. 似乎解决了之前的问题,性能得到提升,但是还是有问题,原因在于在JAVA指令中创建对象和赋值是分开操作的,
  38. 也就是instance = new Singleton();语句是分开操作执行的,但是JVM并不保证这两个操作的顺序是先后执行的,
  39. 它可能为新的Singleton实例分配空间,然后直接复制给instance成员
  40. 然后再去初始化Singleton实例,假设有线程A和B
  41. 1,A,B同时进入第一个if判断
  42. 2,A首先进入synchronized模块,发现instance为null,开始执行instance = new Singleton();
  43. 3,由于JVM的一些优化操作,JVM先划出了一些空白内存给Singleton的实例instance,但并未初始化instance,A便离开了synchronized模块
  44. 4,B发现instance不为null便直接离开了
  45. 5,B打算使用instance实例发现它没有初始化,编译器出错!!!
  46. 因此最好使用饿汉式!!
复制代码
回复 使用道具 举报
懒汉式 一般都是面试考的。
     开发用饿汉式比较好。    饿汉式安全。 懒汉式不是很安全。
           核心原因就是懒汉式不安全!

而且如果懒汉式要想安全的话,需要加同步,但加上同步之后,效率会变低,为了解决效率变低的问题需要进行双重判断,最后代码就变成了下面那样,很麻烦的,所以还是用饿汉式好了

  1. class DanLi{
  2.         private DanLi(){}
  3.         private static DanLi danLi;
  4.         private static DanLi getInstance(){
  5.                 if (danLi==null) {
  6.                         synchronized (DanLi.class) {
  7.                                 if (danLi==null) {
  8.                                         danLi=new DanLi();
  9.                                 }
  10.                         }
  11.                 }
  12.                 return danLi;
  13.         }
  14. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
ily521125 + 1

查看全部评分

回复 使用道具 举报
懒汉式 一般都是面试考的。
     开发用饿汉式比较好。    饿汉式安全。 懒汉式不是很安全。
           核心原因就是懒汉式不安全!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马