导读:话说姑娘我一直想着分个总结设计模式来着,一直没把这个派上日程,现在看一本书,里面提到了一些设计模式,现在就总结总结。话说我之前写单例模式,一直都是按照大话设计模式上的那种写法,也就是传统的加锁,加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这种形式的咯!



posted on 2017-01-13 21:15  何红霞  阅读(125)  评论(0编辑  收藏  举报