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