A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

文章来源:https://blog.csdn.net/a2572371/article/details/78150243

本次直接应用经典案列


单例模式:饿汉模式以及懒模式

饿汉模式:线程安全,不会产生多个实例。但如果加载耗时,增加项目初始化时间,如果在运行过程中,没有用到,可能增加空间的浪费

懒汉模式:充分利用资源,实现懒加载策略。(可能线程不安全,需要用户自己优化)


例子

饿汉模式

/** * Description:饿汉模式 * User: lc * Date: 2017/9/30 0030 * Time: 下午 3:52 */public class HungrySingleton {    /**     * 利用classLoader加载     */private static final HungrySingleton hungrySingleton = new HungrySingleton();    /**     * 私有的构造函数:不让外界创建     */private HungrySingleton() {    }    //提供唯一对外,反射除外public static HungrySingleton getInstance() {        return hungrySingleton;    }}
懒汉模式:几种变形


1.不加任何修饰(不安全)


/** * Description:懒汉模式 * User: lc * Date: 2017/9/30 0030 * Time: 下午 3:58 */public class LazySingleton {    /**     * 未初始化     */private static LazySingleton instance;    private LazySingleton() {    }    public static LazySingleton getInstance() {        //第一次调用会初始化.不过多线程情况下,会重复初始化(线程安全问题)if (instance == null) instance = new LazySingleton();        return instance;    }}

2.加synchronized(不安全)

/** * Description:懒汉模式 * User: lc * Date: 2017/9/30 0030 * Time: 下午 3:58 */public class LazySingleton1 {    /**     * 未初始化     */private static LazySingleton1 instance;    private LazySingleton1() {    }    public static LazySingleton1 getInstance() {        if (instance == null) {            //但是如果线程A和B同时执行到了Synchronized(singleton.class),            // 虽然也是只有一个线程能够执行,假如线程B先执行,线程B获得锁,线程B执行完之后,线程A获得锁,            // 但是此时没有检查singleton是否为空就直接执行了,所以还会出现两个singleton实例的情况synchronized(LazySingleton1.class)            {                instance = new LazySingleton1();            }        }        return instance;    }}

2.加synchronized以及判断是否NULL(不安全)

[java] view plain copy





  • <code class="language-java">/**
  • * Description:懒汉模式:双重检查
  • * User: lc
  • * Date: 2017/9/30 0030
  • * Time: 下午 3:58
  • */  
  • public class LazySingleton2 {  
  •     /**
  •      * 要volatile修饰
  •      * 理由:比如2个线程A/B线程。
  •      */  
  •     private  static LazySingleton2 instance;  
  •   
  •     private LazySingleton2() {  
  •   
  •     }  
  •   
  •     public static LazySingleton2 getInstance() {  
  •   
  •         if (instance == null) {  
  •             synchronized (LazySingleton2.class) {  
  •   
  •                 if(instance == null)  
  •                     //此处还是有问题:虽然做了双重判断。 因为 newLazySingleTon1()是非原子操作  
  •                     //  A a=new A()  
  •                     //  进行了三步操作:1.申请空间2.将引用指向该空间地址3.初始化构造  
  •                     //在理想情况下,按照1->3->2的步骤执行时,双检锁形式可以正常工作,但是由于Java内存模型,允许重排序,所以  
  •                     //完全可能按照1->2->3的顺序执行,则导致双检锁形式出现问题。即线程1在执行single=new Singleton()语句时,刚好按照1->2->3的顺序                     //执行到step2处,此时,instance指向mem内存区域,而该内存区域未被初始化;同时,线程2在第一个if(instance==null)地方发现instan                     // ce不为null了,于是得到这<span style="font-family:Arial, Helvetica, sans-serif;">个为被初始化的实例instance进行使用,导致错误。</span></code>  



  • //synchronized:允许修饰的对象,可见性,但是可以允许jvm的进行重排序



  • instance = new LazySingleton2();



  • return instance;



  • }







  • }



  • return instance;



  • }



  • }


3.加synchronized以及volatile(安全)
/** * Description:懒汉模式:双重检查 * User: lc * Date: 2017/9/30 0030 * Time: 下午 3:58 */public class LazySingleton2 {    /**     * 要volatile修饰     * 理由:比如2个线程A/B线程。     */private volatile static LazySingleton2 instance;    private LazySingleton2() {    }    public static LazySingleton2 getInstance() {        if (instance == null) {            synchronized (LazySingleton2.class) {                if (instance == null)                    instance = new LazySingleton2();            }        }        return instance;    }}

4.静态内部类(安全)


/** * Description:懒汉模式: * User: lc * Date: 2017/9/30 0030 * Time: 下午 3:58 */public class StaticLazySingleton {    /**     * 1.私有内部类,外部不知道该类的存在     * 2.外部类初始化的时候,该内部类还没加载,只有通过第一次调用才(比如这个例子:触发getInstance())加载,加载是利用jvm加载,而jvm加载某个类,只能加载一次,所以是只能有一个class类。故线程安全     * 3.对外提供唯一的出口     */private StaticLazySingleton() {    }    // 静态内部类private static class StaticLazySingletonInstance    {        private static final StaticLazySingleton staticLazySingleton = new StaticLazySingleton();    }    public static StaticLazySingleton getInstance() {        return StaticLazySingletonInstance.staticLazySingleton;    }}



1 个回复

倒序浏览
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马