标签:
单例模式(Singleton) —— 对象创建型模式
本文记录单例模式从设计理念的简单到复杂,从运行效果的低效到高效,各种不同实现方式。涉及到多线程和JVM。
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
The Singleton Pattern ensures a class has only one instance, and provides a gloable point of access to it.

/**
* @description 最简单的实现,线程不安全。
* @author michael
*/
public class Singleton {
private static Singleton uniqueInstance;
//Other useful Singleton data...
/**
* 构造器私有化
*/
private Singleton() {
}
/**
* @description 抽象工程方法(static factory),获得该类唯一实例。
* @return 唯一实例
*/
public static Singleton getInstance() {
if(null == uniqueInstance) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
//Other useful Singleton methods...
}
使用synchronized关键字,同步getInstance()方法,确保任意时刻只有一个线程可以访问该方法。线程安全,效率低。
/**
* @description 线程安全,效率低。
* @author michael
*/
public class Singleton {
private static Singleton uniqueSingleton;
//Other useful Singleton data...
/**
* 构造器私有化
*/
private Singleton() {
}
/**
* @description 同步方法,线程安全,效率低。
* @return 唯一实例
*/
public static synchronized Singleton getInstance() {
if(uniqueSingleton == null) {
uniqueSingleton = new Singleton();
}
return uniqueSingleton;
}
//Other useful Singleton methods...
}
先于方法调用前创建实例,静态初始化变量。依赖于JVM的实现,虚拟机要确保在任何线程访问静态变量uniqueSingleton之前创建好实例。
/**
* @description move to an eagerly created instance rather than a lazily created one.
* @author michael
*/
public class Singleton {
private static Singleton uniqueSingleton = new Singleton();
//Other useful Singleton data...
/**
* 构造器私有化
*/
private Singleton() {
}
/**
* @description eagerly created
* @return 唯一实例
*/
public static synchronized Singleton getInstance() {
return uniqueSingleton;
}
//Other useful Singleton methods...
}
使用volatile关键字修饰变量,确保多线程访问修改正确。双检测,只有在第一次调用getInstance()才会同步类。版本要求:JDK1.5或以上。
解释下为什么需要双重检测,假设此时uniqueSingleton == null,两个线程同时调用getInstance()方法,由于uniqueSingleton还未创建,
if条件满足,两个线程都会进入if语句内部。但是下一步只有一个线程会拿到锁,进入到同步代码块,此时再次检测依然为空,创建实例,
释放锁,并返回实例。当另一个线程获得锁进入同步代码块时,实例已创建,释放锁返回实例。这是双重检测的情况,如果不在同步块内二次检测,
同样两个线程同时访问getInstance()方法,在if语句内,同步方法块外堵塞。获得锁的线程创建实例、释放锁并返回实例。当另一个线程获得锁执行同步代码时,
没有进行二次检测,尽管此时uniqueSingleton已经被创建,后获得锁的线程依然会再创建一个实例,违反了唯一实例的原则。
/**
* @description double checked
* @author michael
* @see 1.5
*/
public class Singleton {
//volatile 多线程共享变量
private volatile static Singleton uniqueSingleton;
//Other useful Singleton data...
/**
* 构造器私有化
*/
private Singleton() {
}
/**
* @description 双检测
* @return 唯一实例
*/
public static synchronized Singleton getInstance() {
if(uniqueSingleton == null) {
//多线程 可能在这堵塞 双检测 避免重复构造
synchronized(Singleton.class) {
if(uniqueSingleton == null) {
uniqueSingleton = new Singleton();
}
}
}
return uniqueSingleton;
}
//Other useful Singleton methods...
}
解释:当第一次调用getInstance()方法,执行uniqueSingle = new Singleton()这句代码,JVM可能在new Single()并未完全执行,
就已经给uniqueSingleton分配地址(uniqueSingleton != null),而此时如果另一个线程调用getInstance()方法,
就会得到还未完全初始化的uniqueSingleton的引用。实现五使用一个中间变量singleton确保uniqueSingleton的完整性。
/**
* @description double checked
* @author michael
* @see since 1.5
*/
public class Singleton {
//volatile 多线程共享变量
private volatile static Singleton uniqueSingleton;
//Other useful Singleton data...
/**
* 构造器私有化
*/
private Singleton() {
}
/**
* @description 双检测
* @return 唯一实例
*/
public static synchronized Singleton getInstance() {
if(uniqueSingleton == null) {
//多线程 可能在这堵塞 双检测 避免重复构造
synchronized(Singleton.class) {
if(uniqueSingleton == null) {
//avoid getting a reference to an incompletely initialized object
Singleton singleton = new Singleton();
uniqueSingleton = singleton;
}
}
}
return uniqueSingleton;
}
//Other useful Singleton methods...
}
1.对唯一实例的受控访问
2.缩小名空间
3.允许对操作和表示的精化
4.允许可变数目的实例
5.比类操作更灵活
很多模式可以使用单例模式实现。参见抽象工厂模式(Abstract Factory)、建造者模式(Builder),和原型模式(Prototype)。
标签:
原文地址:http://www.cnblogs.com/coderworld/p/design-pattern-singleton.html