| 我们都知道单例,饿汉式和懒汉式可以办到。 饿汉式:
 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: 以后就用你了。 哥们,你呢?
 
 
 |