平安公布对象

  • 在动态初始化函数中初始化一个对象援用
  • 将对象的援用保留到volatile类型域或者AtomicReference对象中
  • 将对象的援用保留到某个正确结构对象的final类型域中
  • 将对象的援用保留到一个由锁爱护的域中
Spring 框架中,Spring治理的类都是单例模式。如何保障一个实例只被初始化一次,且线程平安?通过不同单例的写法,具体形容平安公布对象的四种办法:

在动态初始化函数中初始化一个对象的援用(不举荐)

package com.rumenz.task.single;//线程平安//饿汉模式//动态代码块初始化public class SingletonExample {    private SingletonExample(){        //初始化操作    }    private static SingletonExample singletonExample=null;    static {        singletonExample=new SingletonExample();    }    public static SingletonExample getInstance(){        return singletonExample;    }}//或者package com.rumenz.task.single;//线程平安//饿汉模式//动态代码块初始化public class SingletonExample {    private SingletonExample(){        //初始化操作    }    private static SingletonExample singletonExample=new SingletonExample();    public static SingletonExample getInstance(){        return singletonExample;    }}
毛病:用不必都会初始化对象,如果初始化工作较多,加载速度会变慢,影响零碎性能。

将对象的援用保留到volatile类型或AtomicReference对象中(举荐)

package com.rumenz.task.single;//线程平安//懒汉模式public class SingletonExample1 {    private SingletonExample1() {        //初始化操作    }    // 1、memory = allocate() 调配对象的内存空间    // 2、ctorInstance() 初始化对象    // 3、instance = memory 设置instance指向刚调配的内存    // 单例对象 volatile + 双重检测机制 -> 禁止指令重排    private volatile static SingletonExample1 singletonExample1=null;    //动态工厂办法    public static SingletonExample1 getInstance(){        if(singletonExample1==null){ //双重检测            synchronized(SingletonExample1.class){ //同步锁                if(singletonExample1==null){                    singletonExample1=new SingletonExample1();                }            }        }        return singletonExample1;    }}
长处:按需加载
毛病:第一次初始化的时候可能会比较慢

通过synchronized(不举荐)

package com.rumenz.task.single;public class SingletonExample3 {    //公有构造函数    private SingletonExample3(){        //初始化操作    }    private static SingletonExample3 singletonExample3=null;    //动态的工厂办法    public static synchronized SingletonExample3 getSingletonExample3(){         if(singletonExample3==null){             singletonExample3=new SingletonExample3();         }         return singletonExample3;    }}
毛病:每次进入getSingletonExample3都会加锁,消耗资源,故不举荐应用。

枚举(举荐)

package com.rumenz.task.single;public class SingletonExample4 {    //公有构造函数    private SingletonExample4(){       //初始化    }    public static SingletonExample4 getSingletonExample4(){        return Singleton.INSTANCE.getSingleton();    }    private enum Singleton{        INSTANCE;        private SingletonExample4 singleton;        Singleton(){            singleton=new SingletonExample4();        }        public SingletonExample4 getSingleton(){            return singleton;        }    }}
长处:人造线程平安,可避免反射生成实例,举荐应用