23种设计模式之单例模式
Posted liucg1
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了23种设计模式之单例模式相关的知识,希望对你有一定的参考价值。
单例模式(保证java程序中某个类只有一个实例存在)
单例模式有以下的特点:
- 单例类只能有一个实例
- 单例类必须自己创建自己的唯一的实类
- 单例类必须给其他所有对象提供这一实例
在计算机系统中,线程池,缓存,日志对象,打印机,对话框常常被设计成单例对象。选择单例模式就是为了避免不一致状态。
一、懒汉式
public class Singleton{ private Singleton singleton = null;
private Singleton(){} private static Singleton getSingleton(){ if(singleton = null){ singleton = new Singleton(); } return singleton; } }
Singleton通过将构造器私有化,避免了在类外实例化,Singleton的实例只能通过getSingleton()方法访问(不考虑反射)。
以上的懒汉式的代码是没有考虑线程安全的,可以通过以下三种方式将代码进行改造
1.在getSingleton()方法上添加同步(同步是需要开销的,正常执行的代码我们不需要同步,只需要在对象初始化的时候同步)
private static synchronized Singleton getSingleton(){ if(singleton = null){ singleton = new Singleton(); }
}
2.双重检查锁定(double-checked locking)
public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; }
双重检查锁定存在一个问题,这个问题是由指令重排序引起的。指令重排序是为了优化指令,提高程序运行效率,包括编译器重排序和运行时重排序,指令重排序可以在不影响单线程程序执行结果的前提下进行。例如:instance = new Singleton();可以分解为以下伪代码:
memory = allocate();//1.分配对象的内存空间 ctorInstance(memory);//2.初始化对象 instance = memory;//3.instance指向刚才分配的内存空间
经过指令重排序后:
memory = allocate();//1.分配对象的内存空间 instance = memory;//3.instance指向刚才分配的内存空间 ctorInstance(memory);//2.初始化对象
将第2步和第三部调换顺序后,对于单线程的执行结果是没有影响的,但是对于多线程就不一样了。线程A执行了instance = memory(这对另外一个线程B是可见的),线程B这个时候通过 if(instance == null)判断instance不为空,随机返回,这个时候拿到的是未被完全初始化的实例,在使用的时候会有风险,这就是双重检查锁定存在的问题。
在jdk1.5之后可以使用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; } }
3.静态内部类(占位类)
public class Singleton { private static class InstanceHolder { public static Singleton instance = new Singleton(); } private Singleton() { } public static Singleton getInstance() { return InstanceHolder.instance; } }
二、饿汉式
public class Singleton{ private Singleton singleton = new Singleton(); private Singleton(){} private Singleton getInstance(){ return singleton; } }
以上是关于23种设计模式之单例模式的主要内容,如果未能解决你的问题,请参考以下文章