单例设计模式

单例设计模式

Singleton

知识点:

1.模式定义/应用场景/类图分析

2.字节码知识/字节码指令重排序

3.类加载机制

4.JVM序列化机制

5.单例模式在Spring框架 & JDK源码中的应用

模式定义:

保证一个类只有一个实例,并且提供一个全局访问点

场景:

重量级的对象,不需要多个实例,如线程池,数据库连接池。

1.懒汉模式:

延迟加载, 只有在真正使用的时候,才开始实例化。

1)线程安全问题

2)double check 加锁优化

3)编译器(JIT),CPU 有可能对指令进行重排序,导致使用到尚未初始化

的实例,可以通过添加volatile 关键字进行修饰,

对于volatile 修饰的字段,可以防止指令重排。

java 复制代码
class LazySingleton{
2  private volatile static LazySingleton instance;
3  private LazySingleton(){
4
5  }
6  public static LazySingleton getInstance() {
7  if (instance==null){
8  synchronized (LazySingleton.class){
9  if (instance==null){
10  instance=new LazySingleton();
11  // 字节码层
12  // JIT , CPU 有可能对如下指令进行重排序
13  // 1 .分配空间
14  // 2 .初始化
15  // 3 .引用赋值
16  // 如重排序后的结果为如下
17  // 1 .分配空间
18  // 3 .引用赋值 如果在当前指令执行完,有其他线程来获取实例,将拿到尚未初始化好的
实例
19  // 2 .初始化
20
21
22  }
23  }
24
25  }
26  return instance;
27  }
28 }

2.饿汉模式:

类加载的 初始化阶段就完成了 实例的初始化 。本质上就是借助于jvm

类加载机制,保证实例的唯一性(初始化过程只会执行一次)及线程安

全(JVM以同步的形式来完成类加载的整个过程)。

类加载过程:

1,加载二进制数据到内存中, 生成对应的Class数据结构,

2,连接: a. 验证, b.准备(给类的静态成员变量赋默认值),c.解析

3,初始化: 给类的静态变量赋初值

只有在真正使用对应的类时,才会触发初始化 如( 当前类是启动类即

main函数所在类,直接进行new 操作,访问静态属性、访问静态方

法,用反射访问类,初始化一个类的子类等.)

java 复制代码
// 饿汉模式
2
3 class HungrySingleton{
4  private static HungrySingleton instance=new HungrySingleton();
5  private HungrySingleton(){
6  }
7  public static HungrySingleton getInstance() {
8  return instance;
9  }
10 }

3.静态内部类

1).本质上是利用类的加载机制来保证线程安全

2).只有在实际使用的时候,才会触发类的初始化,所以也是懒加载的一

种形式。

java 复制代码
class InnerClassSingleton{
2
3  private static class InnerClassHolder{
4  private static InnerClassSingleton instance= new InnerClassSingleton();
5  }
6  private InnerClassSingleton(){
7
8  }
9  public static InnerClassSingleton getInstance(){
10  return InnerClassHolder.instance;
11  }
12 }

4.反射攻击实例:

java 复制代码
1 Constructor<InnerClassSingleton> declaredConstructor=InnerClassSingleton.c
lass.getDeclaredConstructor();
2 declaredConstructor.setAccessible( true );
3 InnerClassSingleton innerClassSingleton=declaredConstructor.newInstance();
4
5 InnerClassSingleton instance=InnerClassSingleton.getInstance();
6 System.out.println(innerClassSingleton==instance);

静态内部类防止反射破坏

java 复制代码
1 class InnerClassSingleton {
2
3
4  private static class InnerClassHolder{
5  private static InnerClassSingleton instance= new InnerClassSingleton();
6  }
7  private InnerClassSingleton(){
8
9  if (InnerClassHolder.instance!=null){
10  throw new RuntimeException( " 单例不允许多个实例 " );
11  }
12
13  }
14  public static InnerClassSingleton getInstance(){
15  return InnerClassHolder.instance;
16  }
17 }

5.枚举类型

1)天然不支持反射创建对应的实例,且有自己的反序列化机制

2)利用类加载机制保证线程安全

java 复制代码
1 public enum EnumSingleton {
2  INSTANCE;
3
4  public void print(){
5  System.out.println(this.hashCode());
6  }
7 }

6.序列化

1)可以利用 指定方法来替换从反序列化流中的数据 如下

java 复制代码
1 ANY‐ACCESS‐MODIFIER Object readResolve() throws ObjectStreamException;
java 复制代码
1 class InnerClassSingleton implements Serializable{
2
3  static final long serialVersionUID = 42L;
4
5  private static class InnerClassHolder{
6  private static InnerClassSingleton instance= new InnerClassSingleton();
7  }
8  private InnerClassSingleton(){
9
10  if (InnerClassHolder.instance!=null){
11  throw new RuntimeException( " 单例不允许多个实例 " );
12  }
13
14  }
15  public static InnerClassSingleton getInstance(){
16  return InnerClassHolder.instance;
17  }
18
19  Object readResolve() throws ObjectStreamException{
20  return InnerClassHolder.instance;
21  }
22
23 }

源码中的应用

java 复制代码
1 // Spring & JDK
2 java.lang.Runtime
3 org.springframework.aop.framework.ProxyFactoryBean
4 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
5 org.springframework.core.ReactiveAdapterRegistry
6 // Tomcat
7 org.apache.catalina.webresources.TomcatURLStreamHandlerFactory
8 // 反序列化指定数据源
9 java.util.Currency
相关推荐
王嘉俊92524 分钟前
设计模式--适配器模式:优雅解决接口不兼容问题
java·设计模式·适配器模式
王嘉俊92525 分钟前
设计模式--组合模式:统一处理树形结构的优雅设计
java·设计模式·组合模式
rongqing201926 分钟前
Google 智能体设计模式:多智能体协作
设计模式
李广坤15 小时前
状态模式(State Pattern)
设计模式
李广坤17 小时前
观察者模式(Observer Pattern)
设计模式
李广坤18 小时前
中介者模式(Mediator Pattern)
设计模式
李广坤18 小时前
迭代器模式(Iterator Pattern)
设计模式
李广坤18 小时前
解释器模式(Interpreter Pattern)
设计模式
阿无,21 小时前
java23种设计模式之前言
设计模式
Asort1 天前
JavaScript设计模式(八):组合模式(Composite)——构建灵活可扩展的树形对象结构
前端·javascript·设计模式