单例设计模式

单例设计模式

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
相关推荐
Anurmy32 分钟前
设计模式之适配器模式
设计模式·适配器模式
逆境不可逃1 小时前
【从零入门23种设计模式12】结构型之代理模式(Spring AOP + 自定义注解 + 切面的实战)
设计模式·代理模式
电子科技圈1 小时前
IAR扩展嵌入式开发平台,推出面向安全关键型应用的长期支持(LTS)服务
嵌入式硬件·安全·设计模式·软件工程·代码规范·设计规范·代码复审
像少年啦飞驰点、1 小时前
Java策略模式从入门到实战:小白也能看懂的设计模式指南
java·设计模式·策略模式·编程入门·小白教程
程序员Terry1 小时前
别再用 if-else 堆砌代码了!策略模式让你的代码优雅十倍
java·设计模式
JTCC2 小时前
Java 设计模式西游篇 - 第八回:适配器模式通万国 女儿国语言无障碍
python·设计模式·适配器模式
逆境不可逃2 小时前
【从零入门23种设计模式17】行为型之中介者模式
java·leetcode·microsoft·设计模式·职场和发展·中介者模式
Anurmy2 小时前
设计模式之抽象工厂
设计模式
蜜獾云3 小时前
设计模式之原型模式:以自己为原型,自己实现自己的对象拷贝逻辑
java·设计模式·原型模式
melonbo3 小时前
C++ 中用于模块间通信的设计模式
开发语言·c++·设计模式