黑马程序员技术交流社区
标题:
单例设计模式的问题
[打印本页]
作者:
李伟
时间:
2012-6-15 15:05
标题:
单例设计模式的问题
单例设计模式:解决一个类在内存中只存在一个对象,保证对象在内存中的唯一性
1.为了避免其他程序过多建立该对象,先禁止其他程序建立该对象
2.为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象
3.为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式
在实际应用中,对于事物该怎么描述就怎么描述,当需要保证该事物的对象在内存中的唯一性,只要加上以上三步就可以了。
一、单例设计模式之一:饿汉式(类一进内存就建立对象)
class Singe
{
private Single(){}//禁止其他程序建立对象
private static Single s=new Single();//自定义一个对象
public static Single getInstance()//对外提供访问方式获取自定义对象
{
return s;
}
//其他属性和功能照常
}
二、单例设计模式之二:懒汉式(类刚进内存时对象还没有建立,只有获取对象的方法被调用时才建立对象)
class Singe
{
private Single(){}//禁止其他程序建立对象
private static Single s=null;//定义一个空对象
public static Single getInstance()//对外提供访问方式获取自定义对象
{
if(s==null)
s=new Single();//当该方法被调用时,建立对象
return s;
}
//其他属性和功能照常
}
但是这种方式很不安全,当有两个或两个以上的程序访问该方法时,CPU执行的过程中会不断的在各个程序间切换执行,容易在某段时间内造成多个程序卡在if(s==null)和s=new Single();之间,导致最后在堆内存中创建了多个对象,保证不了对象在内存中的唯一性,就有了安全隐患。
为了解决懒汉式的这个安全隐患,有两种方式:
1.给获取对象的方法上锁
public static synchronized Single getInstance()//加上sychronized关键字,给方法上锁
{
if(s==null)
s=new Single();//当该方法被调用时,建立对象
return s;
}
当一个程序正在执行该方法的时候,其他程序进不来,执行完毕其他程序才进得来,从而保证了对象在内存中的唯一性,但是这种解决方式效率很低。
2.在判断语句内读锁
public static Single getInstance()
{
if(s==null)
{
synchronized(Single.class)//进行读锁
{
if(s==null)
s=new Single();//当该方法被调用时,建立对象
}
}
return s;
}
这种方式也保证了对象在内存中的唯一性。
但是不太理解这种解决方式和第一种解决方式有什么区别吗,能解决第一种解决方式效率低的问题吗?
作者:
郑冬
时间:
2012-6-15 15:15
第二种方法并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法过后,先检查实例是否存在,如果不存在才进入下面的同步块,这是第一重检查。进入同步块过后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。这样一来,就只需要同步一次了,从而减少了多次在同步情况下进行判断所浪费的时间。
第二种方法的实现会使用一个关键字volatile,它的意思是:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。
这种实现方式可以实现既线程安全地创建实例,而又不会对性能造成太大的影响。它只是在第一次创建实例的时候同步,以后就不需要同步了,从而加快了运行速度。
作者:
李盼
时间:
2012-6-15 15:24
饿汉式:因为s被定义为静态的,所以类一加载,就会new出对象,无论有没有使用,这个对象一直存在,比较占用内存空间。
懒汉式:当只用要调用这个类的对象时,才去判断s是不是等于null,如果等于,就创建一个对象,如果不等于,就不创建,表面上看是只能创建一个对象,但是我们了解CPU的运行机制后会明白,在某种情况下,会出现第一个调用者刚好判断完if(s==null)这个语句,CPU切换到下一个调用者,这时候两个调用者的判断都通过了,就会new出两个对象,显然就违背了我们单例的初衷。
于是就有后面两种加锁的写法,也就是一个调用者在判断语句到new对象语句完成之前,其他调用者想调用都需要先等待,这样就避免了懒汉式的缺点,又能在不调用的时候不new对象,节约内存!
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2