zoukankan      html  css  js  c++  java
  • 进化的单例模式君

    单例模式应该是涉及学习的较早的模式之一了,俗话说,麻雀虽小......呸呸呸,话又多了

    先来个大纲,对于java而言,你也是单例只有两种。吓死你,回字的四种写法。

    1  饿汉模式(加载类时比较慢,但获取对象时快)

    2 懒汉模式(加载类时快,运行获取对象慢)

    3 通过java加载类时先加载静态{static}资源的手段(歪门邪道)

    4 通过枚举(奇巧淫技)

    -----------------------------------------------------------------------------

    1   饿汉模式大概这样,不多说


    public class SingletonHungry {
    
    	private SingletonHungry() {
    	}
    
    	private static SingletonHungry instance = new SingletonHungry();
    
    	public static SingletonHungry getSingleton() {
    		return instance;
    	}
    
    }
    ---------------------------------------------------------

    懒汉模式的初级样子

    public class SingletonLazy {
    
    	private SingletonLazy() {
    	}
    
    	private static SingletonLazy instance = null;
    
    	public static SingletonLazy getSingleton() {
    		
    		if(instance ==null){
    			instance =new SingletonLazy();
    		}
    		return instance;
    	}
    
    }

    这种模式在单线程下是玩的很high的,但是多线程就扑街了。





    所以,懒汉模式进化 --》 synchronized懒汉模式

    public class SingletonLazy {
    
    	private SingletonLazy() {
    	}
    
    	private static SingletonLazy instance = null;
    
    	public static synchronized SingletonLazy getSingleton() {
    		
    		if(instance ==null){
    			instance =new SingletonLazy();
    		}
    		return instance;
    	}
    
    }



    多线程是安全,但是每次获得对象都需要走一次synchronized这个重量级锁,影响效率啊

    懒汉模式进化 ---》》  双重判断懒汉模式

    public class SingletonLazy {
    
    	private SingletonLazy() {
    	}
    
    	private static SingletonLazy instance = null;
    
    	public static  SingletonLazy getSingleton() {
    		
    		if(instance ==null){
    			  synchronized(SingletonLazy.class){
    				  if(instance==null){
    					  instance =new SingletonLazy();
    				  }
    			  }
    		}
    		return instance;
    	}
    
    }




    但是如果你运气足够好,这种模式下并发还是可能出问题。大概解释是,因为指令重排序的关系,比如三部曲


         (1)分配内存空间。

      (2)初始化对象。

      (3)将内存空间的地址赋值给对应的引用。

    但是由于操作系统可以对指令进行重排序,所以上面的过程也可能会变成如下过程:

      (1)分配内存空间。

      (2)将内存空间的地址赋值给对应的引用。

      (3)初始化对象


    最后懒汉模式究极进化 ,上volatile的懒汉模式

      

    public class SingletonLazy {
    
    	private SingletonLazy() {
    	}
    
    	private static volatile SingletonLazy instance = null;
    
    	public static  SingletonLazy getSingleton() {
    		
    		if(instance ==null){
    			  synchronized(SingletonLazy.class){
    				  if(instance==null){
    					  instance =new SingletonLazy();
    				  }
    			  }
    		}
    		return instance;
    	}
    
    }



    虽然说这个是单例模式不能new出来,但是实际上能够通过反射给弄个新对象。

    不过如果是枚举的单例就不能通过反射弄一个新的。暂时不讨论这个花式摸鱼。


    总结:  单例模式,还是饿汉模式好用........














       

       

  • 相关阅读:
    编译原理
    C++的RTTI
    静态加载dll的问题
    COM编程中的接口查询QueryInterface的实现原理
    com学习笔记(2)基本的com接口QueryInterface的实现
    如何从DLL中生成LIB文件
    CMAP原理及其在MFC中的实现(MAP模板没有顺序遍历的功能)
    多态性vptrvtable
    技术网站
    垃圾事务
  • 原文地址:https://www.cnblogs.com/fangyuandoit/p/13713865.html
Copyright © 2011-2022 走看看