黑马程序员技术交流社区
标题:
单例最理想的实现方式
[打印本页]
作者:
陈军
时间:
2012-11-8 13:21
标题:
单例最理想的实现方式
我们都知道单例,饿汉式和懒汉式可以办到。
饿汉式:
public class Singal {
private Singal(){}
private static Singal instance=new Singal();
public static Singal getInstanceof(){
return instance;
}
}
饿汉式,还是有一定缺点的。 那就是每个对象还未使用,就已经加载了。
如果这个对象比较大。预先加载到内存就会影响性能。由此,延迟加载的懒汉式就来了。
在需要的时候才加载。这似乎达到了某些时候性能上的要求。但是,也带来了安全隐患。
就是多线程的时候。所以我们用了同步synchronized。
懒汉式:
class Single
{
private static Single singObj = null;
private Single(){ }
public synchronized static Single getSingleInstance() {
if(null == singObj ) singObj = new Single();
return singObj;
}
}
但是如果资源竞争比较激烈时,synchronized 会大大降低程序的性能。由此又出来了双重判断锁。
双重判断之懒汉式:
class Single
{
private static Single singleObj = null;
private Single(){ }
public static Single getSingleInstance() {
if(singleObj==null){ //AA
synchronized(Single.class){
if(singleObj==null ) //BB
singleObj = new Single();
}
}
return singleObj; //CC
}
}
可是实际上这个还是有问题的。
假设线程1执行到了AA那里,它判断对象为空,于是线程1执行到BB 去初始化这个对象,但初始化是需要耗费时间的,
但是这个对象的地址其实已经存在了。此时线程2也执行到了AA那里,它判断不为空,于是直接跳到CC得到了这个对象。
但是,这个对象还没有被完整的初始化!得到一个没有初始化完全的对象有什么用!!没有意义。
所以又出来了另一种单例设计模式。代码如下
class Single {
private Single(){}
private static class SingleHolder{
public static final Single instance=new Single();
}
public static Single getInstance(){
return SingleHolder.instance;
}
}
这种方法使用内部类来做到延迟加载对象,在初始化这个内部类的时候,JLS(Java Language Sepcification)会保证这个类的线程安全。
这种写法最大的美在于:完全使用了Java虚拟机的机制进行同步保证,没有一个同步的关键字。也和懒汉式一样是懒加载
所以这就正好结合了饿汉式和懒汉式的优点。
总结: 饿汉式,在资源上有一定程度的浪费。
懒汉式,使用在锁的基础上的,当并发高的时候,会产生阻塞,且严重降低性能。
第三种,也是懒加载。综合了懒汉式和饿汉式的优点。
ps: 以后就用你了。 哥们,你呢?
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2