【设计模式 4】怎样写出更高逼格的单例模式
2017-01-13 21:15
337 查看
导读:话说姑娘我一直想着分个总结设计模式来着,一直没把这个派上日程,现在看一本书,里面提到了一些设计模式,现在就总结总结。话说我之前写单例模式,一直都是按照大话设计模式上的那种写法,也就是传统的加锁,加2把锁的这种方式,今天看了看人家说性能优化,利用内部类,写出了更高逼格的代码,佩服之余,总结一番。
分析:1,给静态成员变量instance初始值赋值null,确保系统启动时没有额外的负载;2,虽然保证了线程安全,但是在多线程环境下,由于引入了Synchronized同步关键字,增加了系统消耗
分析:1,增加了volatile关键字,使得singleton变量不得被重排读写顺序,始终共享内存(不怎么明白的,可以去看看我的博客:【java基础 14】锁的粒度:ThreadLocal、volatile、Atomic和Synchronized)
2,改变了同步的范围,缩小了锁的粒度! 但由于volatile关键字,会影响JVM本身的必要代码优化
分析:通过使用内部类,当StaticSingleton被加载时,其内部类不会被初始化,也就是说,当StaticSingleon类被载入JVM时,不会初始化单例类,只有当getInstance方法被调用时,才会加载SingletonHolder类,初始化instance。实例的建立是在类加载时完成,所以天生对多线程友好,不用使用关键字,节省消耗!
一、两种常见写法分析
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这种形式的咯!相关文章推荐
- 【设计模式 4】怎样写出更高逼格的单例模式
- 设计模式怎样解决设计问题[笔记]
- DAO到底是怎样一种设计模式?EJB是DAO设计模式的一种实现吗?
- 怎样写出好代码——设计原则
- 怎样使用设计模式
- 设计模式怎样解决设计问题
- 怎样使用设计模式
- 设计模式怎样解决设计问题
- 设计模式怎样解决设计问题[1] 寻找合适的对象
- [Java设计模式](一)怎样实现Singleton(单例)模式编程
- 怎样让孩子爱上设计模式 —— 7.适配器模式(Adapter Pattern)
- >--设计模式怎样解决设计问题
- 写出你所知道的设计模式和应用场景
- 怎样学习设计模式和学习其他知识
- 【高质量代码】如何写出更高质量的C/C++代码(2):函数设计
- 怎样才能轻松快速的理解好设计模式
- 怎样才算是一个成熟的程序员:从设计模式谈起
- 《设计模式》学习笔记——设计模式怎样解决设计问题
- 写出你所知道的设计模式和应用场景
- 23种设计模式用英语怎样表达?