单例那些事儿!

单例常见有5钟:懒汉式、饿汉式、同步方法、同步代码块、双重检测。

       对于这5中没什么好说的,网上多的一批。设计思路大致是这样:懒汉式,人如其名,不创建对象,在使用的时候再创建(像lazy load)。饿汉式,也是人如其名,总怕吃不饱,在对象声明的时候就创建成功。对于同步Synchronize代码块和函数,这没啥子说的,You Know。双重检测:为了提高性能,降低同步带来的资源消耗,对实例创建进行两次的判断:

class Single{
   private static Single single = null;
   private Single(){};
   public static getInstance(){
     if(single==null){
        synchronize(Single.class){
           if(single==null)
              single = new Singele();
        }
      }
     return single;
}

这个两次的判断,其实只有第一次的判断是在优化,当else的时候也进入同步块的资源消耗。(到这里基本算完了)。

       但是当你接触《jvm深入理解java虚拟机》这本书后,你会发现,对象的创建其实从某种角度看是分为两步的:1. jvm内存的分配。 2. 对象的初始化。所以,这就导致上述的双重检出现问题:对象在分配到内存但没有初始化完成的时候,下个线程进入判断对象不为null,但是此时拿到的实例确实未完全初始化的实例。必然这样是错滴。这其中有一个现象可以简单了解一下(无序写入)。

       那出现这种low爆的bug怎么办呢?是不是越学越觉得自己的无知。本着一个思考,当你遇见问题的时候,尤其是问题的背后是个大靠山的时候,例如,Sun,Apache这类本身就是BUG的存在,他们一定会帮我们铺设一条便捷的道路。JDK1.5后,引入volatile修饰变量,来避免这种bug的发生。(这逼有点装不下了,这个至于为什么,还不是很清楚,只是知道volatile这个变量居于jvm的内存设计模型有一下功能,这没装,还是知道点的)。

class Single{
   private volatile static Single single = null;
   private Single(){};
   public static getInstance(){
     if(single==null){
        synchronize(Single.class){
           if(single==null)
              single = new Singele();
        }
      }
     return single;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值