双重检查锁定
public class Singleton {
// 静态实例变量加上volatile
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;
}
}
加锁只需在首次初始化时用到,之后调用无需再次加锁,双重检查锁通过先判断对象是否已经被初始化,再决定要不要加锁。
注意
双重检查锁定不再推荐使用,可参考http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
静态内部类
public class Singleton {
// 私有化构造函数
private Singleton() {}
// 利用静态内部类特性实现外部类的单例
private static class SingletonBuilder {
private static Singleton singleton = new Singleton();
}
public static Singleton getInstance() {
return SingletonBuilder.singleton;
}
}
主要原理:Java静态内部类可以访问其外部类的静态成员属性,同时,静态内部类只有被调用时才开始首次加载,利用classloader的机制保证初始化instance时只有一个线程,所以是线程安全的,同时没有由加synchronized同步锁导致性能损耗,更推荐该实现。
枚举
public enum Singleton{
INSTANCE;
}
最简单的实现方式,通过 Java 枚举类型本身的特性,保证了实例创建的线程安全性和实例的唯一性。