单例设计模式Singleton

1.模式定义

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

2.应用场景

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

2.1 源码中的应用

// Spring & JDK
java.lang.Runtime
org.springframework.aop.framework.ProxyFactoryBean
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
org.springframework.core.ReactiveAdapterRegistry
// Tomcat
org.apache.catalina.webresources.TomcatURLStreamHandlerFactory
// 反序列化指定数据源
java.util.Currency

3.实现方式

3.1 懒汉模式

延迟加载, 只有在真正使用的时候,才开始实例化。
1)线程安全问题
2)double check 加锁优化
3)编译器(JIT),CPU 有可能对指令进行重排序,导致使用到尚未初始化
的实例,可以通过添加volatile 关键字进行修饰,
对于volatile 修饰的字段,可以防止指令重排。
public class LazySingletonTest {
    public static void main(String[] args) {
//        LazySingleton singleton = LazySingleton.getInstance();
//        LazySingleton singleton1 = LazySingleton.getInstance();
//        System.out.println(singleton == singleton1);

        Thread thread = new Thread(()->{
            LazySingleton s1 = LazySingleton.getInstance();
            System.out.println(s1);
        });
        thread.start();

        Thread thread2 = new Thread(()->{
            LazySingleton s1 = LazySingleton.getInstance();
            System.out.println(s1);
        });
        thread2.start();
    }
}


class LazySingleton{
    private volatile static LazySingleton singleton = null;
    private LazySingleton(){

    }

    public static LazySingleton getInstance(){
        // synchronized 不建议修饰在方法上,因为方法上每次调用都需要加锁,性能低
        if (singleton == null) {
            synchronized (LazySingleton.class){
                if (singleton == null) {
                    singleton = new LazySingleton();
                    //字节码
                    // 1.分配空间
                    // 2.初始化
                    // 3.引用赋值
                    // 初始化和引用赋值可以不分先后进行
                }
            }
        }
        return singleton;
    }
}

3.2.饿汉模式

类加载的 初始化阶段就完成了 实例的初始化 。本质上就是借助于jvm
类加载机制,保证实例的唯一性(初始化过程只会执行一次)及线程安
全(JVM以 同步 的形式来完成类加载的整个过程)。
类加载过程:
1,加载二进制数据到内存中, 生成对应的Class数据结构,
2,连接: a. 验证, b.准备(给类的静态成员变量赋 默认值 ),c.解析
3, 初始化 : 给类的静态变量赋 初值
只有在真正使用对应的类时,才会触发初始化 如( 当前类是启动类即
main函数所在类,直接进行new 操作,访问静态属性、访问静态方
法,用反射访问类,初始化一个类的子类等.)
class HungerSingleton {
    private static HungerSingleton singleton = new HungerSingleton();

    private HungerSingleton() {

    }

    public static HungerSingleton getInstance() {
        return singleton;
    }
}

3.3 静态内部类

1).本质上是利用类的加载机制来保证线程安全
2).只有在实际使用的时候,才会触发类的初始化,所以也是懒加载的一
种形式。
class InnerClassSingleton {

    private InnerClassSingleton() {
    }

    private static class InnerClassHandle {
        private static InnerClassSingleton singleton = new InnerClassSingleton();
    }

    public static InnerClassSingleton getInstance(){
        return InnerClassHandle.singleton;
    }
}

3.4 反射攻击实例

静态内部类防止反射破坏

相关推荐

  1. 设计模式Singleton

    2024-02-21 06:18:01       46 阅读
  2. 设计模式-模式Singleton

    2024-02-21 06:18:01       53 阅读
  3. 【C++设计模式 -- Singleton模式

    2024-02-21 06:18:01       51 阅读
  4. 设计模式模式 Singleton Pattern

    2024-02-21 06:18:01       53 阅读
  5. 设计模式-模式Singleton Pattern)

    2024-02-21 06:18:01       48 阅读
  6. 设计模式模式Singleton Pattern)

    2024-02-21 06:18:01       36 阅读
  7. 设计模式——模式Singleton

    2024-02-21 06:18:01       29 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-21 06:18:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-21 06:18:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-02-21 06:18:01       82 阅读
  4. Python语言-面向对象

    2024-02-21 06:18:01       91 阅读

热门阅读

  1. 关于TypeReference的使用

    2024-02-21 06:18:01       50 阅读
  2. Hive数据仓库行转列

    2024-02-21 06:18:01       52 阅读
  3. starrocks对大量数据怎么实现hash join

    2024-02-21 06:18:01       45 阅读
  4. npm install一直卡在 sill idealTree buildDeps

    2024-02-21 06:18:01       47 阅读
  5. 机器学习速成

    2024-02-21 06:18:01       56 阅读
  6. 6CCS3ML1 Machine Learning

    2024-02-21 06:18:01       36 阅读
  7. 机器学习 -- 矩阵和向量

    2024-02-21 06:18:01       47 阅读