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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

懒汉式和饿汉式的区别是什么?请举例说明?它们都在什么情况下应用及特点?

7 个回复

倒序浏览
额,我来说说吧
饿汉式
  1. class Single
  2. {
  3.         private Single(){}
  4.         private static Single s = new Single();
  5.         public static Single getInstance()
  6.         {
  7.                 return s;
  8.         }
  9. }
复制代码
懒汉式:
  1. class Single
  2. {
  3.         private Single(){}
  4.         private static Single s ;
  5.         public static Single getInstance()
  6.         {               
  7.                 if(s==null)
  8.                 {
  9.                         s = new Single();       
  10.                 }                       
  11.                 return s;
  12.         }
  13. }
复制代码
要说是在什么时候用到的话,他们都是出现在单例模式下,也就是说,当某一个类你只想让他有一个实例的话,就用得到单例模式了。
饿汉式是类一加载进内存就创建好了对象。开发时一般用饿汉式。
因为懒汉式有线程安全隐患。       
懒汉式则是类才加载进内存的时候,对象还没有存在,只有调用了getInstance()方法时,对象才开始创建。

懒汉式和饿汉式的区别就是,懒汉式是延迟加载,然后多个线程同时操作懒汉式时就有可能出现线程安全问题,解决线程安全问题可以加同步来解决。
但是加了同步之后,每一次都要比较锁,效率就变慢了,所以可以加双重判断来提高程序效率。
懒汉式修改后代码如下:
  1. class SingleDemo
  2. {
  3.         //懒汉式
  4.         private static SingleDemo s=null;
  5.         private SingeleDemo(){}
  6.         public static SingleDemo getSingeleDemo()
  7.         {
  8.                 if(s==null)  //双重判断,在这里再判断一次,这样就可以避免判断锁,从而提高效率。
  9.                 {
  10.                         synchronized(SingleDemo.class)
  11.                         {
  12.                                 if(s==null)
  13.                                         s = new SingleDemo();
  14.                         }
  15.                 }       
  16.                 return s;       
复制代码
。。。。。。。
如果真的在写代码的时候特别是多线程中用到单例模式,我觉得还是饿汉式比较好,因为用懒汉式一个不仔细,可能就漏掉同步,然后线程就不安全了。

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 田林 于 2012-5-11 13:00 编辑

比较:
饿汉式是线程安全的,在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变。
懒汉式如果在创建实例对象时不加上synchronized,则可能会导致对对象访问的线程不安全。
推荐使用饿汉式 .从实现方式来讲他们最大的区别就是懒汉式是延时加载,他是在需要的时候才创建对象,而饿汉式在虚拟机启动的时候就会创建,使用的场合根据具体环境和个人习惯而定.

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

回复 使用道具 举报
单例模式下有懒汉式和饿汉式两种实现方式。
懒汉式:是当有需求时才创建对象,当涉及到多线程时,必须加锁,实现同步,效率慢,
饿汉式:是一初始化就有一个实例对象,安全,高校,但当没有被调用时就会比懒汉式多创建了以个对象

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

回复 使用道具 举报
懒汉式是方法被调用时,才初始化,也叫做对象延迟加载,它存在着安全隐患,需要同步,效率不高
饿汉式是类一进内存就创建好了对象,线程安全
因此一般定义单例都是用饿汉式。
例子的话你看看基础视频里的讲单例的那两节就行了
应用的话主要是用到饿汉式,在一个类中只需要一个对象,不需要其他新对象时用到,如程序的配置文件
饿汉式主要是涉及的知识点多,所以面试中常用

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 王怡然 于 2012-5-11 13:15 编辑
  1. class Teacher
  2.         {
  3.                 private Teacher(){}//私有化构造函数;

  4.                 private static Teacher t;//定义一个指向,指向为空;

  5.                 public static Teacher getInstance()
  6.                 {
  7.                         if(t==null)//判断此对象是否被调用;
  8.                         {
  9.                                 t = new Teacher();//如果没有调用就创建对象,并指向t;
  10.                         }
  11.                         return t;//如果有对象,就直接返回给调用者;
  12.                 }
  13.         }
复制代码
  1. class Student
  2.         {
  3.                 private Student(){}//把构造函数私有化;

  4.                 private static Student s = new Student();//类一加载就直接创建对象;

  5.                 public static Student getInstance()
  6.                 {
  7.                         return s;//把这个对象返回给调用者;
  8.                 }
  9.         }
复制代码
Student类一进内存,就已经创建好了对象。这个称之为饿汉式;

对象是方法被调用时,才初始化,也叫做对象的延时加载。称之为:懒汉式。
Teach类进内存,对象还没有存在,只有调用了getInstance方法时,才建立对象。
但是懒汉式有缺点,就是线程不安全的问题,这个在毕老师的课程中有详细的介绍,我觉得你应该好好看看课程了,这个偷懒不得...

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

回复 使用道具 举报
杨威 中级黑马 2012-5-11 16:00:11
7#
本帖最后由 杨威 于 2012-5-11 16:05 编辑

以前写学习日记时写到过这个小知识点,帖一下供参考,不是在网上粘贴的哦。
单例设计模式是java23种设计模式之一,它是解决一个类在内存中只存在一个对象。
如果有两个程序去访问同一个文件C,如程序A与程序B,其中程序A对文件进行修改,B程序进行读取,按说B会读取到A修改后的文件信息,是不是这样呢?实质上我们知道他们要想访问文件C就必须在各自的程序中建立文件对象,那这个时候在各自的程序中建立的对象就不是同一个对象了,这就要保证对象在内存中的唯一性了。
那么保证一个类唯一思路就有以下几点:
1, 为了保证其他对象建立过多对象,先禁止其他程序建立该类对象,只要将构造函数私有化。
2, 但有必须保证其他程序可以访问该类对象,就在本类中自定义一个对象。
3, 为了方便其他程序对自定义对象的访问,可以提供一些访问方式,也即提供一个方法可以获取到本类对象。
代码的实现如下:
class Single
{
       privateSingle(){}
       privatestatic Single s = new Single();//下面静态方法在访问类中成员,故成员也应被静态修饰
       /*只需要get方法,不需要set方法,因为只能获取对象*/
       publicstatic Single getInstance()//不能再创建,只能类名调用。故静态修饰
       {
              returns ;
       }
}
这样,在主函数中再new对象,就会保证在内存中只会有一个对象,而其他只是引用在指向它。在代码中描述事物时,事物该怎么描述就怎么描述,只要将上面的代码加入就可以保证对象的单一,这就是单例设计模式。

单例设计模式有两种方式,一个是饿汉式,一个是懒汉式。
饿汉式代码是:
class Single
{
       privatestatic Single s = new Single();
       privateSingle(){}
       publicstatic Single getInstance()
       {
              returns;
       }
}
之所以称为饿汉式是因为Single类一进内存,就已经建立好了对象。
懒汉式代码是:
class Single
{
       privatestatic Single s = null;
       privateSingle(){}
       publicstatic Single getInstance()
       {
              if(s==null)
                     s= new Single();
              returns ;
       }
}
之所以称为懒汉式是Single类进内存对象还没有存在,只用调用了getInstance方法时,才创建对象。
而懒汉式是有安全问题的,因为s是共享数据,如果多个线程并发的访问getInstance方法,那就有可能共同在getInstance方法中操作,比如线程A在判断了s==null后挂起,而这时线程B在判断后也进入了,并一样的挂起。此时A醒了,new一个s对象,在这之后B线程也醒了,也new了一个对象,这就出现问题了,就违背了单例设计模式的初衷了。这就要加入同步锁了。改进后代码如下:
class Single
{
       privatestatic Single s = null;
       privateSingle(){}
       publicstatic Single getInstance()
       {
              /*加入双重判断模式,提高效率*/
              if(s==null)
              {
                     synchronized(Single.class)//这里不能是this,因为静态
                     {
                            if(s==null)
                                   s= new Single();
                     }
              }
              returns ;
       }
}
从以上分析可以看出,饿汉式较懒汉式简单,而且能保证对象的唯一性,所以在实际应用中,还是以饿汉式为主,不建议使用懒汉式。

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

回复 使用道具 举报
1.问懒汉式和饿汉式有什么不同?
   懒汉式的特点在于实例的延时加载,
2。问懒汉式实例延时加载有什么问题?
   多线程时会出现同步问题。加同步解决,加同步的方式,用同步函数和同步代码块都行 但是低效
   用双重判断问题可以解决这个问题。加同步时使用的锁是哪一个?该类所属的字节码文件对象。
问题会是,写一个延时加载的单例设计模式。



//饿汉式
class Single
{
private static Single s = new Single();
private Single(){}
public static Single getInstance()
{
        return s;
}
}




//懒汉式

class  Single
{
private static Single s=null;
private Single(){}

public static Single getInstance()
{
  if(s==null)
  {
   synchronized(Single.class)//静态同步函数的琐是class
   {
    if(s==null)
     s=new Single();
   }
  }
  return s;
}


}

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马