设计模式之单例模式 Singleton实现
Posted 大白
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之单例模式 Singleton实现相关的知识,希望对你有一定的参考价值。
饿汉式
- 饿汉式单例模式,static变量会在类装载时初始化,此时也不会涉及多个线程对象访问该对象的问题。虚拟机保证只会装载一次该类,肯定不会发生并发访问的问题,
因此可以省略synchronized关键字
- 问题:如果只是加载本类,而不是要调用getInstance(),甚至永远没有调用,则会造成资源浪费
public class SingletonDemo1 { //类初始化时,立即加载这个对象(没有延时加载的优势),,记载类时,天然的是线程安全的 private static SingletonDemo1 instance = new SingletonDemo1(); private SingletonDemo1(){ }; //方法没有同步,效率高 public static SingletonDemo1 getInstance(){ return instance; } }
懒汉式
- Lazy Load,延时加载,真正用到的时候再加载
- 每次都得使用同步,synchronized,效率就底下了。
public class SingletonDemo2 { //类初始化时,不初始化这个对象,(延时加载,真正用到的时候再创建) private static SingletonDemo2 instance ; private SingletonDemo2(){ }; //方法同步,效率低 public static synchronized SingletonDemo2 getInstance(){ if(instance==null){ instance= new SingletonDemo2(); } return instance; } }
双重检测锁
- 双重检测判断
- 使用volatile关键字,保证可见性
public class Singleton { private volatile static Singleton sSingleton; private Singleton() { } public static Singleton getSingleton() { if (sSingleton == null) { synchronized (Singleton.class) { if (sSingleton == null) { sSingleton = new Singleton(); } } } return sSingleton; } }
静态内部类
- 外部类没有static关键字,所以不会立即加载
- 只有调用getInstance()时才会加载静态内部类,线程安全。instance前面加了static final关键字,因此保证了内存中只有这样一个实例存在,且只能赋值一次,final保证线程安全
- 具有并发高效调用和延迟加载的双重优点
public class SingletonDemo3 { private static class SingletonClassInstance{ private static final SingletonDemo3 instance = new SingletonDemo3() ; } private SingletonDemo3(){ } public static SingletonDemo3 getInstance(){ return SingletonClassInstance.instance; } }
枚举实现
- 实现简单
- 枚举本身就是单例模式
public enum SingletonDemo4 { //枚举元素本身就是单例对象 INSTANCE; //添加自己需要的操作 public void singletonOperation(){ } }
如何防止反射和反序列化漏洞
- 反射可以破解上面几种(不包含枚举式)实现方式 --------------------------可以在构造方法中手动抛出异常控制
- 反序列化可以破解上面几种(不包含枚举式)实现方式
-------可以通过定义readResolve()防止获得不同对象。
--------反序列化时,如果对象所在类定义了readResolve(),定义返回哪个对象,实际是一种回调。
public class SingletonDemo5 { //类初始化时,不初始化这个对象,(延时加载,真正用到的时候再创建) private static SingletonDemo5 instance ; private SingletonDemo5(){ if(instance !=null){ throw new RuntimeException(); } } //方法同步,效率低 public static synchronized SingletonDemo5 getInstance(){ if(instance==null){ instance= new SingletonDemo5(); } return instance; } //反序列化时,如果定义了readResolve(),则直接返回此方法指定的对象,而不需要单独创建新的对象 private Object readResolve(){ return instance; } }
五种单例模式比较
单例对象占用资源少,不需要延时加载 -------枚举类好于饿汉式
单例对象占用资源大,需要延时加载 -------静态内部类好于懒汉式
以上是关于设计模式之单例模式 Singleton实现的主要内容,如果未能解决你的问题,请参考以下文章