主要角色
- 单例模式本身
职责
在任何情况下,都绝对只有一个实例
代码
基础版
线程安全
public class Singleton{
private static Singleton singleton;
static{
singleton = new Singleton();
}
private Singleton(){
// do something
}
public static Singleton getInstance(){
return singleton;
}
}
问题
- 可以使用反射的方式创建不止一个单例。
- 单例如果不使用还是被创建出来了。
懒汉模式-用的时候在创建
不能使用反射创建。
线程安全
public class LazySingleton {
private static LazySingleton lazySingleton = null;
private LazySingleton(){
if(lazySingleton != null){
throw new RuntimeException("单例构造器禁止反射调用");
}
}
public synchronized static LazySingleton getInstance(){
if(lazySingleton == null){
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
问题
-
synchronized加在 static 方法上,实际上就是加在类上。性能不高。
懒汉双重检查锁模式-兼顾线程安全和性能问题
使用 volatile 避免指令重排序
public class LazyDoubleCheckSingleton {
private volatile static LazyDoubleCheckSingleton lazyDoubleCheckSingleton = null;
private LazyDoubleCheckSingleton(){
}
public static LazyDoubleCheckSingleton getInstance(){
if(lazyDoubleCheckSingleton == null){
synchronized (LazyDoubleCheckSingleton.class){
if(lazyDoubleCheckSingleton == null){
lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton();
// 1.分配内存给这个对象
// 2.初始化对象
// 3.设置lazyDoubleCheckSingleton 指向刚分配的内存地址
// 可能会出现指令重排序,执行顺序变成 1->3->2,的时候,另一个线程判断 lazyDoubleCheckSingleton 不为,直接返回了。
}
}
}
return lazyDoubleCheckSingleton;
}
}
静态内部类模式
与懒汉双重检查锁模式作用相同,只是使用静态内部类来避免指令重排序。
public class StaticInnerClassSingleton {
private static class InnerClass{
private static StaticInnerClassSingleton staticInnerClassSingleton = new StaticInnerClassSingleton();
}
public static StaticInnerClassSingleton getInstance(){
return InnerClass.staticInnerClassSingleton;
}
private StaticInnerClassSingleton(){
if(InnerClass.staticInnerClassSingleton != null){
throw new RuntimeException("单例构造器禁止反射调用");
}
}
}
枚举模式
public enum Singleton {
INSTANCE;
public void whatever() {
}
}
技巧
- 因为单例的特性,和并发的特性相似,所以特别要注意线程安全问题。
- 因为单例模式经常被问到,所以单例模式的实现会多样。










网友评论