思维盛宴之设计模式-单例模式Singleton Pattern
来源:互联网 发布:剑三脸型数据是视频 编辑:程序博客网 时间:2024/05/01 22:32
1. 适用场景
单例模式可能是众多设计模式中相对最简单的一种了。它能够保证在一个jvm虚拟机中单例类只有一个实例。通常,在应用软件系统中,线程池,缓存,日志,工具或其他拥有管理功能的类都被实现为单例,因为他们在整个系统中只需要存在一份,也只需要对外提供一个全局的访问点即可。
单例的实现有三种方式:
- 懒汉式
- 饿汉式
- 登记式
登记式的底层实现依然是懒汉式或饿汉式(将不同类的单例们存放在一个内部的Map中,对于已经登记过的实例,则从Map直接返回,对于没有登记的,先登记,再返回),因此这里就不做讨论了。我们主要来看前两种,也是大家见得最多的两种。
2. 代码实现
2.1 懒汉式
public class Singleton { private Singleton() {} //全局单例 private static Singleton instance =null; //静态方法 public static Singleton getInstance() { if (instance == null) { //(1) instance = new Singleton(); } return instance; }}
上面的代码就是一个最简单的懒汉式单例实现。通过private访问修饰符限定构造器对外不可见,因此无法在外部手动创建一个Singleton实例,同时对外提供一个全局的访问点getInstance方法,以统一的控制对象的获取。这个获取过程在内部保证了对象只会创建一份。注意,这里的全局单例指的是在同一个jvm中的全局单例。
要指出的是,实际上即使构造函数被设置为private,java中的反射机制(如通过setAccessible方法设置方法可见并随后直接调用构造器)仍然可以对其进行调用并实例化一个单例类,这里对这种情况暂不做考虑。
上述的懒汉式单例实现在多线程并发的情况下是不安全的,因为多个线程可能同时执行到(1)处,发现不存在单例实例,于是各自构造器出一个实例,单例存在多个副本,状态不一致了,也就失去了其作用。
那么如果想要把上面的代码变成线程安全的,如何做呢?
有三种方法:
getInstance方法上加同步
public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance;}
double check:双重判断
//全局单例//使用volatile关键字来声明单例对象(new Singleton()是非原子操作)private static volatile Singleton instance = new Singleton();public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { //双重检查防止再次new出实例 instance = new Singleton(); } } } return instance;}
使用静态内部类改造
private static class LazyHolder { private static final Singleton INSTANCE = new Singleton();}public static final Singleton getInstance() { return LazyHolder.INSTANCE;}
方法3既可以实现线程安全(类加载时已自行实例化INSTANCE),又能够避免同步带来的性能影响。
2.2 饿汉式
private Singleton() {}//全局单例private static Singleton instance = new Singleton();//静态方法public static Singleton getInstance() { return instance;}
饿汉式与上面的方法3有点相似,在类初始化时就已经创建好一个静态的全局单例供系统使用,并且jvm的类加载机制保证了这个类只被加载一次,因此它也是线程安全的。
3. 思考与总结
饿汉式依靠jvm的类加载机制天生实现了线程安全,而懒汉式本身则是线程不安全的,使用上述的3种方法可以对其改造,其中第3种在性能上更优(因为避免了同步)。
通常,饿汉式的实现方式已经能够满足绝大多数需求,性能不错,代码也少,方便且易理解。
- 思维盛宴之设计模式-单例模式Singleton Pattern
- 思维盛宴之设计模式-适配器模式Adapter Pattern
- 思维盛宴之设计模式-构建者模式Builder Pattern
- 思维盛宴之设计模式-代理模式Proxy Pattern
- 设计模式之单模式 Singleton pattern
- Delphi设计模式之单例模式(Singleton Pattern)
- Delphi设计模式之单例模式(Singleton Pattern)
- Net设计模式实例之单例模式( Singleton Pattern)
- 设计模式笔记之单例模式(Singleton Pattern)
- C++设计模式之Singleton pattern(单例模式)
- 设计模式之单例模式(Singleton Pattern)
- 设计模式之-单例模式(Singleton Design Pattern)
- JAVA设计模式之 单例模式【Singleton Pattern】
- 设计模式之单例模式(Singleton Pattern)C++实现
- 设计模式(创建型)之单例模式(Singleton Pattern)
- Java开发之设计模式--单例模式(Singleton Pattern)
- 设计模式之单例模式(Singleton pattern)
- 设计模式之---单例模式(Singleton Design Pattern)
- Eclipse SVN插件设置ignore文件
- chrome表单自动填充去掉input黄色背景解决方案
- zookeeper的一致性协议:Zab
- HNACM(六) 第三题 最舒适的路线
- poj 1328 【Radar Installation】【贪心】
- 思维盛宴之设计模式-单例模式Singleton Pattern
- 贫下中农版jQuery
- Linux 学习笔记之Makefile单个c文件的编写
- Java接口详解
- lk 打印 device-tree dtb 信息
- Theano, Keras的安装指南和部分疑难杂症
- Android中ExpandableListView控件基本使用
- HDU_1232
- 使用ZooKeeper ACL特性进行znode控制