设计模式之单例模式
来源:互联网 发布:伊尔18客机数据 编辑:程序博客网 时间:2024/06/05 06:02
1. 什么是单例模式
- 该类只能有一个实例;
- 该类能够自动实例化;
- 对整个系统可见,即必须向整个系统提供这个实例。
2. 实现
a. 饿汉式
public class Singleton { private static Singleton instance=new Singleton(); private Singleton(){ } public static Singleton getInstance(){ return instance; } }
实现简单,基于classloder机制避免了多线程的同步问题,不过,instance在类装载时就实例化,没有进行延迟加载。
b. 懒汉
public class Singleton{ private static Singleton instance; private Singleton(){ } public static Singleton getInstance(){ if(instance==null){ instance=new Singleton(); } return instance; } }
lazy loading很明显,但是在多线程时不能正常工作
c. 懒汉 + 同步方法
public class Singleton{ private static Singleton instance; private Singleton(){ } public static synchronized Singleton getInstance(){ if(instance==null){ instance=new Singleton(); } return instance; } }
解决了多线程同步,但同步范围太大,在实例化instacne后,获取实例仍然是同步的,效率低
d. 懒汉 + 同步块
public class Singleton{ private static Singleton instance; private Singleton(){ } public static Singleton getInstance(){ if(instance==null){ synchronized(Singleton.class){ instance=new Singleton(); } } return instance; } }
缩小了同步范围,但存在创建多个实例的可能,比如线程A和B同时执行到了synchronized(Singleton.class),线程B获得锁执行完之后,线程A获得锁,但是此时没有检查singleton是否为空就直接执行了,所以还会出现两个singleton实例的情况
e. 懒汉 + 双重检查(DCL)
public class Singleton{ private static volatile Singleton instance; private Singleton(){ } public static Singleton getInstance(){ if(instance==null){ synchronized(Singleton.class){ if(instance==null){ instance=new Singleton(); } } } return instance; } }
instance=new Singleton()并不是原子语句,实际包括了下面三大步骤:
1. 为对象分配内存
2. 初始化实例对象
3. 把引用instance指向分配的内存空间
处理器会进行指令重排序优化,当重排后执行顺序为1,3,2时,若线程1执行到3,此时线程2判断instance!=null,直接返回instance引用,但实际上实例对象还没有初始化完毕,使用它可能会造成程序崩溃。
e. 懒汉 + 双重检查 + volatile
public class Singleton{ private static volatile Singleton instance; private Singleton(){ } public static Singleton getInstance(){ if(instance==null){ synchronized(Singleton.class){ if(instance==null){ instance=new Singleton(); } } } return instance; } }
使用volatile提供内存屏障,限制处理器进行指令优化重排,保证了instance赋值操作是最后一步完成,不会再出现instance在对象没有初始化时就不为null的情况
f. 懒汉+静态内部类
public class Singleton{ private Singleton(){ } public static Singleton getInstance(){ return InstanceHolder.instance; } static class InstanceHolder{ private static Singleton instance = new Singleton(); } }
静态内部类在Singleton类被装载时并不会立即实例化,而是在调用getInstance方法,才会装载SingletonInstance类,从而完成Singleton的实例化。
类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
g. 枚举
public enum EasySingleton { INSTANCE; }
借助JDK1.5中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。
- 设计模式之 单例设计模式
- 设计模式之 单例设计模式
- 设计模式之单例设计模式
- 设计模式之-----------单例设计模式
- 设计模式之:单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之-单例设计模式
- 设计模式之单例设计模式 标签: 设计模式
- 设计模式之单例
- 设计模式之单例
- 设计模式之 单例
- 使用maven profile实现多环境可移植构建
- Linux环境下设置命令别名(alias)
- 深入理解MVC
- [乐意黎转载]CentOS yum 源的配置与使用
- MongoDB数据库读书笔记
- 设计模式之单例模式
- 爬虫基础理论篇
- vuejs与外界通信
- liunx mysql主从复制
- ambari-server- 资源provider分析
- 对301重定向到HTTPS前遭遇中间人攻击的分析
- ubuntu 如何打开rar 文件及zip 包解压出来的文件名乱码
- 第六届Java软件开发B组
- 数据库连接池 dbcp与c3p0的使用