1.UML类图
Singleton类,定义一个getInstance操作,允许客户端访问它的唯一实例。getInstance是一个静态方法,主要负责创建自己的唯一实例。
2.示例代码
(1)没有考虑多线程的单例模式
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
在这里Singleton类封装了它的唯一实例,这样它可以严格地控制客户怎样访问它以及何时访问它。简单地说就是对唯一实例的受控访问。但这种实现方式,在高并发下会出现Singleton不是单例的情况,因为有可能当一个线程判断instance为null,因为另一个线程初始化Singleton的过程还没有结束,如此便会出现Singleton不是单例的情况。
(2)加锁确保多线程单例
public class LockSingleton {
private static LockSingleton instance;
private static Object locker = new Object();
private LockSingleton() {
}
public static LockSingleton getInstance() {
synchronized (locker) {
if (instance == null) {
instance = new LockSingleton();
}
return instance;
}
}
}
lock确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待,直到该对象被释放。不对instance加锁是因为instance实例有没有被创建过还不知道。但这种实现的性能不好,线程每次都会加锁。
(3)双重检测锁
public class DoubleLockSingleton {
private static DoubleLockSingleton doubleLockSingleton;
private static Object locker = new Object();
private DoubleLockSingleton() {
}
public static DoubleLockSingleton getInstance() {
if (doubleLockSingleton == null) {
synchronized (locker) {
if (doubleLockSingleton == null) {
doubleLockSingleton = new DoubleLockSingleton();
}
}
}
return doubleLockSingleton;
}
}
这种方法知识在实例未被创建时再加锁处理,效率要比单个锁高。
(4)静态初始化
public class StaticSingleton {
private StaticSingleton() {
}
// 静态内部类
private static class StaticSingletonHolder {
private static StaticSingleton instance = new StaticSingleton();
}
public static StaticSingleton getInstance() {
return StaticSingletonHolder.instance;
}
}
这种静态初始化的方式是在自己被加载时就将自己实例化,所以被形象地称之为饿汉式单例类,上面三种是要在第一次被引用时,才将自己实例化,所以被称为懒汉式单例类。
3.特点
保证类一个类仅有一个实例,并提供一个访问它的全局访问点。通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的方法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。