佛山网站建设兼职,作风建设问题在哪里,免费做网站公司,怎么做跳转网站【创建型设计模式】单例模式
这篇博客接下来几篇都将阐述设计模式相关内容。
接下来的顺序大概是#xff1a;单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式。
一、什么是单例模式
单例模式是一种创建型设计模式#xff0c;它保证一个类仅有一个实例#…【创建型设计模式】单例模式
这篇博客接下来几篇都将阐述设计模式相关内容。
接下来的顺序大概是单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式。
一、什么是单例模式
单例模式是一种创建型设计模式它保证一个类仅有一个实例并提供一个全局访问点。 核心思想 限制类的实例化次数确保全局只有一个实例。提供统一访问该实例的方法。 Client 为客户端Singleton 是单例类通过调用 Singleton.getInstance() 来获取实例对象。
二、单例模式的 6 种方法
(1) 饿汉模式
public class Singleton {private static Singleton instance new Singleton();private Singleton() {}public static Singleton getInstance() {return instance;}
}特点
初始化时间 类加载时即完成实例化。访问效率 调用 getInstance 时无需等待性能高。
优点
基于类加载机制天然线程安全。实现简单适用于单例对象较少被频繁初始化的场景。
缺点
无法延迟加载如果实例从未被使用会浪费内存。
(2) 懒汉模式线程不安全
public class Singleton {private static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance null) {instance new Singleton();}return instance;}
}特点
初始化时间 第一次调用时才实例化。访问效率 多线程环境下存在问题可能生成多个实例。
优点 延迟加载节省资源。
缺点 线程不安全多个线程同时调用可能创建多个实例导致单例失效。
(3) 懒汉模式线程安全
public class Singleton {private static Singleton instance;private Singleton() {}public static synchronized Singleton getInstance() {if (instance null) {instance new Singleton();}return instance;}
}特点
线程安全性 使用 synchronized 关键字确保多线程下只生成一个实例。
优点 在多线程环境中保证安全。
缺点 同步锁导致性能下降每次调用 getInstance 都需排队影响效率。
(4) 双重检查模式DCL
public class Singleton {// 1. 声明 volatile 修饰的静态实例变量private static volatile Singleton instance;// 2. 私有化构造方法防止外部直接实例化private Singleton() {}// 3. 提供对外获取实例的静态方法public static Singleton getInstance() {// 第一次检查避免不必要的同步if (instance null) {synchronized (Singleton.class) { // 加锁// 第二次检查确保实例未被其他线程创建if (instance null) {instance new Singleton();}}}return instance;}
}特点
性能优化 减少同步开销。线程安全 使用 volatile 避免指令重排序确保多线程环境下正确创建实例。
优点 资源利用率高延迟初始化线程安全性能优于懒汉模式线程安全版。
缺点 实现复杂某些情况下可能出现 DCL 失效问题如旧版 JVM。 DCL 模式的核心思想 DCL 的核心是两次检查和同步锁的结合。 **第一次检查if (instance null)**在大多数情况下实例已经被初始化可以直接返回不需要加锁。减少了不必要的同步提高性能。 **加锁synchronized**在实例尚未初始化时进入临界区防止多个线程同时创建实例。 **第二次检查if (instance null)**加锁后再次检查实例是否为 null防止多个线程同时通过第一次检查确保单例对象只被创建一次。 **volatile 关键字**确保 instance 的修改对所有线程立即可见防止指令重排序导致未完全初始化的对象被其他线程访问。 为什么需要 volatile 问题指令重排序 在没有 volatile 修饰时JVM 编译器和 CPU 可能对以下代码进行优化 instance new Singleton();这一行代码可能被分解为以下三步 为对象分配内存。初始化对象。将对象引用赋值给 instance。 但实际执行中可能发生指令重排序 为对象分配内存。将对象引用赋值给 instance。初始化对象。 如果线程 A 在步骤 2 后被切换线程 B 进入并访问了 instance此时会得到一个未初始化的对象导致程序行为不可预期。 解决方法volatile 关键字禁止指令重排序确保对象初始化完成后才将引用赋值给 instance。 (5) 静态内部类单例模式
public class Singleton {// 私有化构造方法防止外部实例化private Singleton() {}// 静态内部类持有单例实例private static class SingletonHolder {private static final Singleton INSTANCE new Singleton();}// 提供全局访问点返回静态内部类中的单例实例public static Singleton getInstance() {return SingletonHolder.INSTANCE;}
}特点
延迟加载 第一次调用 getInstance 时才加载内部类完成实例化。线程安全 内部类加载机制天然线程安全。
优点
实现简单避免同步开销。兼具延迟加载和线程安全推荐使用。
缺点 无法控制实例销毁适用单例生命周期较长的场景。 静态内部类的加载时机 在 Java 中类的加载是延迟的只有在被真正使用时才会加载静态内部类。 主类被加载时静态内部类不会被加载。 只有在调用静态内部类中的成员时静态内部类才会被加载。 类加载的线程安全性 JVM 在加载类时会自动保证线程安全。 静态变量 INSTANCE 只会被初始化一次。 (6) 枚举单例
public enum Singleton {INSTANCE; // 枚举单例的唯一实例// 单例类的其他方法public void doSomething() {System.out.println(Singleton instance is working!);}
}特点
线程安全 枚举的线程安全由 JVM 保证。防反序列化破坏 默认枚举实例不可反序列化。
优点
实现简单天生线程安全。避免反序列化和反射破坏单例。
缺点
不支持延迟加载。某些场景下如需要灵活实例化控制不适用。
public class Test {public static void main(String[] args) {Singleton instance Singleton.INSTANCE;instance.doSomething();}
}为什么枚举单例是线程安全的 **JVM 保证**枚举类型在类加载时会由 JVM 初始化类加载过程是线程安全的。 **枚举的单一实例特性**枚举中的每个实例在加载时被自动创建并且不可被外部修改。 三、单例实现对比
实现方式是否线程安全是否延迟加载性能复杂度饿汉模式是否高简单懒汉模式不安全否是高简单懒汉模式同步是是低频繁加锁简单双重检查模式DCL是是较高中等静态内部类模式是是高简单枚举单例是否高简单