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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 韩国军 中级黑马   /  2012-5-16 13:07  /  1926 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

懒汉式和饿汉式在多线程中有什么区别?具体的过程是怎么实现的?

6 个回复

倒序浏览
(1)饿汉式 开发用这种方式。
        class Student
        {
                private Student(){}

                private static Student s = new Student();

                public static Student getInstance()
                {
                        return s;
                }
        }
        (2)懒汉式 面试写这种方式。多线程的问题?
        class Teacher
        {
                private Teacher(){}

                private static Teacher t;

                public static Teacher getInstance()
                {
                        if(t==null)
                        {
                                t = new Teacher();
                        }
                        return t;
                }
        }

比较:
   饿汉式是线程安全的,在类创建的同时就已经创建好一个静态的对象供系统使用,以后不在改变
   懒汉式在创建实例对象时如果不加上synchronized则会导致对对象的访问不是线程安全的
   推荐使用第一种  

评分

参与人数 2技术分 +1 黑马币 +1 收起 理由
职业规划-刘倩老师 + 1
韩国军 + 1

查看全部评分

回复 使用道具 举报
懒汉式有安全隐患问题,
  1. class Single
  2. {
  3.         private static Single s = null;
  4.         private Single(){}
  5.         public static Single getInstance()
  6.         {
  7.                 if (s==null)
  8.                         s = new Single();
  9.                 return s ;
  10.         }
  11. }
复制代码
之所以称为懒汉式是Single类进内存对象还没有存在,只用调用了getInstance方法时,才创建对象。
而懒汉式是有安全问题的,因为s是共享数据,如果多个线程并发的访问getInstance方法,那就有可能共同在getInstance方法中操作,比如线程A在判断了s==null后挂起,而这时线程B在判断后也进入了,并一样的挂起。此时A醒了,new一个s对象,在这之后B线程也醒了,也new了一个对象,这就出现问题了,就违背了单例设计模式的初衷了。就要加入同步代码块来解决,麻烦。
饿汉式就不会出现这样的问题,看代码:
  1. class Single
  2. {
  3.         private static Single s = new Single();
  4.         private Single(){}
  5.         public static Single getInstance()
  6.         {
  7.                 return s;
  8.         }
  9. }
复制代码
Single类一进内存就已经创建好了对象,不会出现类似于懒汉的问题。我们使用单例就是因为要再内存中保证唯一对象,所以不建议使用懒汉式

评分

参与人数 2技术分 +1 黑马币 +1 收起 理由
职业规划-刘倩老师 + 1
韩国军 + 1

查看全部评分

回复 使用道具 举报
懒汉式:
class Single

{

        private static Single s = null;

        private Single(){}

        public static Single getInstance()

        {

                if (s==null)

                        s = new Single();

                return s ;

        }

}
懒汉式在多线程中是不安全的,因为这个类的对象在内存中只有在调用getInstance()方法的时候才会被创建。而s又是static的,所以在多线程中有多个线程访问getInstance()
的时候,就需要同步代码块来保证安全问题。(为什么会不安全请看毕老师的那个售票系统的例子)。
class Single

{

        private static Single s = new Single();

        private Single(){}

        public static Single getInstance()

        {

                return s;

        }

}
饿汉式就不会出现这样的状况,因为它定义的static是它的类对象,也就是说它共享的是类对象,这样当有多个线程访问的时候多个线程操作的是同一个对象,那么每次调用方法就相当于一个对象在调用方法,这样就不会出现安全问题。
所以饿汉式是推荐使用的。懒汉式最好不在多线程中使用,会很麻烦。但是饿汉式也有它不好的地方,由于饿汉式在类加载时就完成了初始化,所以类加载较慢。不过相对获取对象的速度快。

使用中看需求吧,貌似饿汉式用的比懒汉式多很多。


回复 使用道具 举报
       饿汗式和懒汉式在多线程中的区别
       饿汗式在多线程中,因为取得对象的getInstance方法体中只有一句返回对象语句,所以不会出现安全问题题。  
        而懒汉式是延时加载的,就是被调用时实例才加载,问题就出现在这。如果多个线程同时调用,比如A,B两个线程同时调用,因为线程具有随机性,就有可能在实例没加载时,A通过if判断以后停住了,因为此时可能A没获取CPU执行权,而此时实例也还没被加载,也就是S==null,所以B获取CPU执行权有机会进来了,然后创建了对象,等到A获取执行权了以后,还会再创建一个新对象,这就是问题所在了,要解决这个问题,只能同步处理了,而同步处理有两种方式,同步函数和同步代码块,如果使用同步函数,在多线程调用时,每次都要同步判断,就会消耗资源,想要减少资源浪费,可以双重判断同步代码块,也就是下面这种形式。毕老师的day11-15讲的很清楚了,不懂再看看
//饿汗式
class Single
{
        private static final Single s = new Single();
        private  Single(){}
        public static Single getInstance()
        {
                return s;
        }

}
//懒汉式
class SingleLan
{
        private static SingleLan s = null;
        private  SingleLan(){}
        public static SingleLan getInstance()
        {
                if (s==null)
                {
                        return new SingleLan();
                }
                return s;
        }
}
//以下方式解决懒汉式多线程安全问题
class SingleLan
{
        private static SingleLan s = null;
        private  SingleLan(){}
        public static SingleLan getInstance()
        {
                if(s==null)
                        synchronized(SingleLan.class)
                        {
                                if (s==null)
                                {
                                        return new SingleLan();
                                }
                                return new SingleLan();
                        }
                return s;
        }
}
回复 使用道具 举报
1,饿汉式。先初始化对象。
class Single {
     Single s = new single();
      private Single(){}
      public static Single getInstance(){
      return s;
}
}
回复 使用道具 举报
2,懒汉式(也称作延迟加载)。对象被调用时才初始化。
class Single{
     private static Single s = null;
     private Single(){}
     public static Single getInstance{
            if(s == null)
                  s=new Single();
            return s;
       }
}
饿汉式特点:Single类一进内存,就已经创建好了对象。
懒汉式特点:Single类一进内存,对象还没有存在,只有调用getInstance方法时,才建立对象,这就称为 延迟加载。
开发时:建议使用饿汉式。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马