单例模式
1. 分析
- 定义:包证一个类仅有一个实例,并提供一个全局访问点
- 类型:
创建型
适用场景:
- 想确保任何情况下都绝对只有一个实例
优点:
- 在内存中只有一个实例,减少了内存开销
- 可以避免对资源的多重占用
- 设置全局访问点,严格控制访问
缺点:
- 没有接口,扩展困难
重点:
- 私有构造器
- 线程安全
- 延迟加载
- 序列化和反序列化安全
- 反射
2. 示例
2.1 懒汉式
public class LazySingleton {
private static LazySingleton lazySingleton = null;
private LazySingleton() {
}
public synchronized static LazySingleton getInstance() {
if (lazySingleton == null) {
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
2.2 懒汉式双重锁检测
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 指向刚分配的内存地址
}
}
}
return lazyDoubleCheckSingleton;
}
}
2.3 静态内部类单例模式
public class StaticInnerClassSingleton {
private StaticInnerClassSingleton() {
}
private static class InnerClass {
private static StaticInnerClassSingleton staticInnerClassSingleton = new StaticInnerClassSingleton();
}
public static StaticInnerClassSingleton getInstance() {
return InnerClass.staticInnerClassSingleton;
}
}
2.4 饿汉式
- 方式1
public class HungrySingleton {
private final static HungrySingleton hungrySingleton = new HungrySingleton();
private HungrySingleton() {
}
public static HungrySingleton getInstance() {
return hungrySingleton;
}
}
- 方式2,使用静态代码块
public class HungrySingleton {
private final static HungrySingleton hungrySingleton;
static {
hungrySingleton = new HungrySingleton();
}
private HungrySingleton() {
}
public static HungrySingleton getInstance() {
return hungrySingleton;
}
}
解决序列化与反序列化对象不一致问题
public class HungrySingleton implements Serializable {
private final static HungrySingleton hungrySingleton;
static {
hungrySingleton = new HungrySingleton();
}
private HungrySingleton() {
}
public static HungrySingleton getInstance() {
return hungrySingleton;
}
private Object readResolve() {
return hungrySingleton;
}
}
实现
Serializable
接口,添加readResolve
方法
2.5 容器式
public class ContainerSingleton {
private ContainerSingleton() {
}
private static Map<String, Object> singletonMap = new ConcurrentHashMap<>();
public static void putInstance(String key, Object instance) {
if (StringUtils.isNotBlank(key) && instance != null) {
if (!singletonMap.containsKey(key)) {
singletonMap.put(key, instance);
}
}
}
public static Object getInstance(String key) {
return singletonMap.get(key);
}
}
2.6 ThreadLocal式
public class ThreadLocalInstance {
private ThreadLocalInstance() {
}
private static final ThreadLocal<ThreadLocalInstance> threadLocal = new ThreadLocal<ThreadLocalInstance>() {
@Override
protected ThreadLocalInstance initialValue() {
return new ThreadLocalInstance();
}
};
public ThreadLocalInstance getInstance() {
return threadLocal.get();
}
}