4.Singleton-单例模式
2016-12-28 17:23
309 查看
Singleton 单例模式
单例模式:单例类只能有一个实例。
单例类必须自己创建自己的唯一实例。
单例类必须给所有其他对象提供这一实例。
好处:
某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。
省去了new操作符,降低了系统内存的使用频率,减轻GC压力。
有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了。(比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程。
示例类图:
示例代码:
饿汉式(线程安全)
//饿汉式单例类.在类初始化时,已经自行实例化 public class Singleton { private static final Singleton INSTANCE = new Singleton(); private Singleton() {} public static Singleton getInstance() { return INSTANCE; } }
这种方式基于classloder机制避免了多线程的同步问题。
懒汉式(线程不安全)
public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
达到了lazy loading的效果,但是致命的是在多线程不能正常工作。
懒汉式(线程安全)
public class Singleton { private static Singleton instance; private Singleton (){} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
达到了lazy loading的效果且线程安全,但是效率低每次都做了不必要的同步。
双重校验锁 DCL(懒汉式,线程安全)
public class Singleton { private volatile static Singleton singleton; private Singleton (){} public static Singleton getSingleton() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
静态内部类(懒汉式,线程安全)
public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }
利用了classloder的机制来保证初始化instance时只有一个线程,与第1种有所区别,这种达到了lazy loading效果。
枚举(饿汉,线程安全)
public enum Singleton { INSTANCE; public void otherMethod() { } }
不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。enum是jdk5新加入的,继承至Enum的类都为final,且不能继承其他类,equals,hashCode,compareTo等部分方法不能重写。
容器实现单例模式
public class SingletonManager { private static Map<String, Object> objMap = new HashMap<String, Object>(); private SingletonManager() { } public static void registerService(String key, Object instance) { if (!objMap.containsKey(key)) { objMap.put(key, instance); } } public static Object getService(String key) { return objMap.get(key); } }
用SingletonManager 将多种的单例类统一管理,在使用时根据key获取对象对应类型的对象。
这种方式使得我们可以管理多种类型的单例,并且在使用时可以通过统一的接口进行获取操作,降低了用户的使用成本,也对用户隐藏了具体实现,降低了耦合度。
注意
如果Singleton实现了java.io.Serializable接口,那么这个类的实例就可能被序列化和复原。不管怎样,如果序列化一个单例类的对象,接下来复原多个那个对象,那就会有多个单例类的实例了。- 解决方法: 加入readResolve()方法。
public class Singleton implements Serializable { private static final long serialVersionUID = 1L; private Singleton() { } public void otherMethod() { } private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } /** * {@see java.io.Serializable} */ private Object readResolve() throws ObjectStreamException { return getInstance(); } }
相关文章推荐
- PropertyChangeListener简单理解
- 什么是设计模式
- 设计模式之创建型模式 - 特别的变量问题
- 七、设计模式——装饰模式
- 设计模式总结
- 设计模式之创建型模式
- 浅谈设计模式的学习
- 设计模式---状态模式在web前端中的应用
- Ruby设计模式编程之适配器模式实战攻略
- 实例讲解Ruby使用设计模式中的装饰器模式的方法
- 设计模式中的模板方法模式在Ruby中的应用实例两则
- Ruby设计模式编程中对外观模式的应用实例分析
- 实例解析Ruby设计模式编程中Strategy策略模式的使用
- Ruby中使用设计模式中的简单工厂模式和工厂方法模式
- Ruby使用设计模式中的代理模式与装饰模式的代码实例
- 详解组合模式的结构及其在Ruby设计模式编程中的运用
- C# 设计模式系列教程-建造者模式
- C#编程中使用设计模式中的原型模式的实例讲解
- 使用设计模式中的工厂方法模式进行C#编程的示例讲解
- 实例解析C#设计模式编程中简单工厂模式的使用