单例模式
使用场景
全局只有一个实例。确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。
饿汉式
- 优点:线程安全,能够确保 任何时候访问都是同一个实例
- 缺点:不管是否使用这个实例,只要类加载了,就会初始化实例,这样造成空间浪费。
public class HungrySingle {
private static HungrySingle hungrySingle = new HungrySingle();
private HungrySingle() {
}
public static HungrySingle getInstance() {
return hungrySingle;
}
}
懒汉式
- 优点:只有用到这个实例时候,才会创建实例,不会造成空间浪费
- 缺点:如果不加锁,会造成线程不安全,加锁性能下降
public class LazySingle {
private static LazySingle lazySingle;
private LazySingle() {
}
public static synchronized LazySingle getInstance() {
if (lazySingle == null) {
lazySingle = new LazySingle();
}
return lazySingle;
}
}
双重检查式
- 优点:用到的时候,才会创建这个实例,并且线程安全
- 变量需要使用 volatile 修饰,避免编译器会进行指令重排
public class LazyDoubleCheckSingle {
private volatile static LazyDoubleCheckSingle single;
private static boolean flag = true;
private LazyDoubleCheckSingle() {
}
public static LazyDoubleCheckSingle getInstance() {
if (single == null) {
synchronized (LazyDoubleCheckSingle.class) {
if (single == null) {
single = new LazyDoubleCheckSingle();
}
}
}
return single;
}
}
匿名内部类式
- 优点:用到实例的时候,才会创建实例,线程安全
public class LazyInnerClassSingle {
private LazyInnerClassSingle() {
}
public static LazyInnerClassSingle getInstance() {
return LazyHolder.LAZY;
}
private static class LazyHolder {
private static final LazyInnerClassSingle LAZY = new LazyInnerClassSingle();
}
}
枚举类式
- 优点:全局只有一个实例,不会被反射破坏单例,不会序列化破坏单例
public enum EnumSingle {
INSTANCE;
private Object data;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public static EnumSingle getInstance() {
return INSTANCE;
}
}
ThreadLocal 线程单例
- 优点:每个线程中,对象是单例的。
public class ThreadLocalSingle {
private static final ThreadLocal<ThreadLocalSingle> threadLocalInstance = new ThreadLocal<ThreadLocalSingle>() {
@Override
protected ThreadLocalSingle initialValue() {
return new ThreadLocalSingle();
}
};
private ThreadLocalSingle() {
}
public static ThreadLocalSingle getInstance() {
return threadLocalInstance.get();
}
}