2024.10.11 | cuithink | 701次围观
4. 单例模式
单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供了一种全局访问点以访问该实例
饿汉式和懒汉式的区别
初始化时机不同:饿汉式单例模式在类加载时就立即初始化并创建单例对象,而懒汉式单例模式则是在第一次使用时才会进行初始化,并创建单例对象。
线程安全性不同:饿汉式单例模式在类加载时就创建了单例对象,因此天生就是线程安全的。而懒汉式单例模式在第一次使用时才会创建单例对象,如果多个线程同时调用getInstance()方法,可能会创建出多个单例对象,因此需要进行同步控制来保证线程安全。
内存占用不同:饿汉式单例模式在类加载时就创建了单例对象,因此占用的内存较多。而懒汉式单例模式在第一次使用时才会创建单例对象,因此占用的内存相对较少。
实现方式
饿汉式
class Singleton { // 1. 加载该类时,单例就会自动被创建 private static Singleton ourInstance = new Singleton(); // 2. 构造函数 设置为 私有权限 // 原因:禁止他人创建实例 private Singleton() { } // 3. 通过调用静态方法获得创建的单例 public static Singleton newInstance() { return ourInstance; } }
懒汉式
class Singleton { private static Singleton ourInstance = null; private Singleton() { } public static Singleton newInstance() { // 加入双重校验锁 // 校验锁1:第1个if if( ourInstance == null){ // ① synchronized (Singleton.class){ // ② // 校验锁2:第2个 if if( ourInstance == null){ ourInstance = new Singleton(); } } } return ourInstance; } } // 说明 // 校验锁1:第1个if // 作用:若单例已创建,则直接返回已创建的单例,无需再执行加锁操作 // 即直接跳到执行 return ourInstance // 校验锁2:第2个 if // 作用:防止多次创建单例问题 // 原理 // 1. 线程A调用newInstance(),当运行到②位置时,此时线程B也调用了newInstance() // 2. 因线程A并没有执行instance = new Singleton();,此时instance仍为空,因此线程B能突破第1层 if 判断,运行到①位置等待synchronized中的A线程执行完毕 // 3. 当线程A释放同步锁时,单例已创建,即instance已非空 // 4. 此时线程B 从①开始执行到位置②。此时第2层 if 判断 = 为空(单例已创建),因此也不会创建多余的实例
静态内部类
原理 根据 静态内部类 的特性(外部类的加载不影响内部类),同时解决了按
需加载、线程安全的问题,同时实现简洁
1. 在静态内部类里创建单例,在装载该内部类时才会去实例化单例
2. 线程安全:类是由 JVM 加载,而 JVM 只会加载1遍,保证只有1个单例
枚举
因为枚举类型是线程安全的,并且只会装载一次,设计者充分的利用了枚
举的这个特性来实现单例模式,枚举的写法非常简单,而且枚举类型是所
用单例实现中唯一一种不会被破坏的单例实现模式。
为什么枚举类可以阻止反射的破坏?
首先枚举类中是没有空参构造方法的,只有一个带两个参数的构造方法 真正原因是: 反射方法中不予许使用反射创建枚举对象
粤ICP备16076548号
发表评论