zoukankan      html  css  js  c++  java
  • 【设计模式 4】怎样写出更高逼格的单例模式

    导读:话说姑娘我一直想着分个总结设计模式来着,一直没把这个派上日程,现在看一本书,里面提到了一些设计模式,现在就总结总结。话说我之前写单例模式,一直都是按照大话设计模式上的那种写法,也就是传统的加锁,加2把锁的这种方式,今天看了看人家说性能优化,利用内部类,写出了更高逼格的代码,佩服之余,总结一番。


    一、两种常见写法分析

    1.1,单锁懒汉式

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

    分析:1,给静态成员变量instance初始值赋值null,确保系统启动时没有额外的负载;2,虽然保证了线程安全,但是在多线程环境下,由于引入了Synchronized同步关键字,增加了系统消耗


    1.2,流行的双重检查机制

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


    分析:1,增加了volatile关键字,使得singleton变量不得被重排读写顺序,始终共享内存(不怎么明白的,可以去看看我的博客:【java基础 14】锁的粒度:ThreadLocal、volatile、Atomic和Synchronized) 2,改变了同步的范围,缩小了锁的粒度! 但由于volatile关键字,会影响JVM本身的必要代码优化


    二、逼格比较高的两种写法

    2.1,使用内部类

    public class StaticSingleton{
    	private static class SingletonHolder{
    		private static StaticSingleton instance=new StaticSingleton();
    	}
    	
    	public static StaticSingleton getInstance(){
    		return SingletonHolder.instance;
    	}
    }

    分析:通过使用内部类,当StaticSingleton被加载时,其内部类不会被初始化,也就是说,当StaticSingleon类被载入JVM时,不会初始化单例类,只有当getInstance方法被调用时,才会加载SingletonHolder类,初始化instance。实例的建立是在类加载时完成,所以天生对多线程友好,不用使用关键字,节省消耗!


    2.2,避免串行创建多个实例

    public class SerSingleton implements java.io.Serializable{
    	String name;
    	
    	private SerSingleton(){
    		name="SerSingleton";
    	}
    	
    	private static SerSingleton instance=new SerSingleton();
    	public static SerSingleton getInstance(){
    		return instance;
    	}
    	
    	private Object readResolve(){
    		return instance;//阻止生成新的实例,总是返回当前对象
    	}
    }
    分析:序列化操作提供了一个很特别的钩子(hook)-类中具有一个私有的被实例化的方法readresolve(),这个方法可以确保类的开发人员在序列化将会返回怎样的object上具有发言权。在实现了readResolve()方法后,readObject()方法形同虚设,直接使用readResolve()替换了原本的返回值,从而在形式上构造了单例


    三、总结

    由于自己在基础上的不牢固,很多时候写代码都不严谨高效,比如这次的单例模式,就想着线程安全,然后也没有想着性能怎么样的问题。就跟LinkList和ArrayList一样,到哪儿都用ArrayList,额。。。。。遇到一个,总结一个,下次写单例,就不再写Synchronized这种形式的咯!



  • 相关阅读:
    七、基础数据类型补充
    JavaScript DOM 鼠标拖拽
    JavaScript JSON 与 AJAX
    JavaScript DOM 事件模型
    JavaScript DOM 样式操作
    JavaScript DOM 常用尺寸
    JavaScript 日期与计时器
    JavaScript DOM 基础
    JavaScript 数组
    JavaScript 对象拷贝
  • 原文地址:https://www.cnblogs.com/hhx626/p/7534612.html
Copyright © 2011-2022 走看看