单例模式是设计模式里最常见一种,也是比较简单的一个模式。它确保了一个类只有一个实例,且提供一个全局访问点

单例模式的几种实现方式

经典实现

1
2
3
4
5
6
7
8
9
10
public class Singleton {
private static Singleton uniqueInstance;
private Singleton(){}
public static Singleton getInstance(){
if(uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
key points
  • 一个静态私有变量: 记录Singleton类的唯一实例
  • 一个私有的构造方法: 确保只有Singleton内部可以调用
  • 静态的getInstance()方法:用来外部调用获取实例
延迟实例化

从实现代码里我们可以看出,如果不需要这个实例,它就永远也不会产生,即延迟实例化(lazy instance)

适用于多线程的实现

在多线程情况下,为了确保只创建一个实例,可以在getInstance()方法上加上synchronized关键字
但是这样会导致每次调用该方法获取实例的时候都进行同步操作,过于累赘。
由于只有第一次创建实例的时候才需要同步,可以进行如下的改进

急切创建实例
1
2
3
4
5
6
7
8
public class Singleton{
// 在静态初始化中创建单例,保证其线程安全性
private static Singleton uniqueInstance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return uniqueInstance;
}
}
双重检查枷锁

另外一种保证线程安全的方式,就是利用双重检查锁, 即, 首先检查实例是否已经创建了, 如果尚未创建,“才”进行同步。 这样一来,只有一次会同步,正是我们想要的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Singleton{
// volatile 关键字确保当uniqueInstance变量被初始化成Singleton时,多个线程正确处理uniqueInstance变量
private volatile static Singleton uniqueInstance;
private Singleton(){}
public static Singleton getInstance() {
if(uniqueInstance == null) {
synchronized(Singleton.class) {
if(uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}