单例模式(静态内部类实现)

本文详细解析了静态内部类实现的懒加载模式,通过在静态内部类中创建实例,结合final关键字确保线程安全,同时实现了延迟加载,提高了并发效率。

静态内部类实现方式(也是一种懒加载方式) 要点:

外部类没有static属性,则不会像饿汉式那样立即加载对象只有真正调用了getInstance()才会加载静态内部类,加载类时是线程安全的。

sc是static final类型,保证了内存中只有一个实例存在,而且只能被赋予一次从而保证了线程安全性。

兼备了并发高效调用和延迟加载的优势。

 

public class StaticClass {
    private static class  StaticClassSc{
        private static final StaticClass sc = new StaticClass();
    }
    public static StaticClass getInstance() {
        return StaticClassSc.sc;
    }
    private StaticClass() {};
}
public class Client {
    public static void main(String[] args) {
        StaticClass sc = StaticClass.getInstance();
        StaticClass sc1 = StaticClass.getInstance();
        System.out.println(sc==sc1);//结果为true
    }
}

<think>我们正在讨论单例模式中的静态内部类实现方式。根据引用内容,静态内部类单例模式被广泛认为是一种优雅且高效的方式。以下是关于该方法的详细介绍: 1. **实现原理**: - 在静态内部类中创建,外部类(Manager)的`getInstance()`方法返回内部类(ManagerHolder)的静态。 - 关键点:静态内部类不会在外部类加载时立即加载,而是在首次调用`getInstance()`时才会加载内部类,从而实现**懒加载**(延迟初始化)[^4]。 - JVM在加载类时会确保其线程安全,因此能保证实的唯一性。 2. **代码结构**: ```java public class Singleton { // 1. 私有构造方法 private Singleton() {} // 2. 静态内部类,持有 private static class Holder { private static final Singleton INSTANCE = new Singleton(); } // 3. 全局访问点 public static Singleton getInstance() { return Holder.INSTANCE; } } ``` 3. **核心优势**(整合引用内容): - **懒加载**:外部类加载时不触发内部类的加载,只有调用`getInstance()`时才创建实,节省内存[^4]。 - **线程安全**:JVM在初始化类(此处是内部类)时自动保证线程安全性(通过类加载锁)[^2][^4]。 - **无锁高效**:访问`getInstance()`无需同步锁,性能接近直接内存访问[^3]。 - **代码简洁**:避免复杂的双重检查锁定(Double-Checked Locking)逻辑[^1]。 4. **与饿汉式对比**: - 饿汉式(`private static final Singleton instance = new Singleton();`)在类加载时就初始化,可能提前消耗资源。 - 静态内部类将初始化延迟到需要时,同时保持同等安全性。 5. **适用场景**: - 需要延迟加载且高并发的场景(如Spring中的Bean)[^2]。 - 替代双检锁的复杂实现(如Java EE容器管理组件)[^3]。 ### 延伸思考:为何静态内部类能保证线程安全? - 根据Java语言规范,类的初始化(执行`<clinit>`方法)由JVM保证线程安全(即使多个线程同时调用`getInstance()`,内部类也只加载一次)[^4]。 - 示:若线程A和B同时首次调用`getInstance()`,其中一个线程会优先获得类加载锁,另一个等待初始化完成,不会重复创建实。 §§相关问题§§ 1. 静态内部类单例模式与双检锁模式在性能上有何差异? 2. 如何破坏静态内部类实现单例模式?如何防御? 3. 在哪些场景下应避免使用静态内部类单例模式? 4. Spring框架如何利用静态内部类原理管理Bean? [^1]: 设计模式3:单例模式静态内部类单例模式 [^2]: Java单例模式静态内部类实现原理剖析 [^3]: 静态内部类实现_单例模式详解 [^4]: java静态内部类单例模式_单例模式-静态内部类实现及原理剖析 </think> # 单例模式静态内部类实现方法详解 ## 一、静态内部类实现原理 静态内部类单例模式利用Java类加载机制实现线程安全的多线程单例模式: 1. **延迟加载机制**: - 当外部类加载时,内部类不会被立即初始化 - 只有调用`getInstance()`时,才触发内部类的加载和实化 [^4] 2. **线程安全保障**: - JVM保证类的加载过程是原子操作,确保线程安全 - 多线程首次调用时不会创建多个实 3. **类加载时间点**: $$ \text{外部类加载} \nrightarrow \text{内部类加载} $$ $$ \text{首次调用} \text{getInstance()} \rightarrow \text{内部类加载} $$ ## 二、具体实现分析 ```java public class Singleton { // 私有构造器,防止外部实化 private Singleton() {} // 静态内部类 private static class Holder { // 内部类中创建 private static final Singleton INSTANCE = new Singleton(); } // 全局访问点 public static Singleton getInstance() { return Holder.INSTANCE; // 触发Holder类加载 } // 业务方法 public void businessMethod() { // ... } } ``` ## 三、核心优势分析 1. **懒加载(Lazy Loading)**: - 避免初始化开销:仅在第一次调用时创建实 [^4] - 内存效率:不占用内存空间直到实际需要时 2. **线程安全**: - JVM类加载器确保初始化过程的线程安全 - 避免显式同步带来的性能损耗 [^2] 3. **代码简洁性**: - 避免复杂的双重检查锁定逻辑 - 无`volatile`等特殊修饰符需求 [^1] 4. **性能优异**: - 实访问接近直接内存访问速度($O(1)$时间复杂度) - 无锁机制带来的性能损耗(VS双检锁中CAS操作) ## 四、与其他实现方式对比 | 实现方式 | 线程安全 | 懒加载 | 性能 | 复杂性 | |---------------|----------|--------|--------|--------| | 静态内部类 | ✓ | ✓ | 最高 | 简 | | 枚举 | ✓ | ✗ | 高 | 简 | | 双重检验锁 | ✓ | ✓ | 中高 | 复杂 | | 饿汉式 | ✓ | ✗ | 高 | 简 | | 同步方法 | ✓ | ✓ | 低 | 简 | ## 五、适用场景 1. **高并发服务**:如电商平台的库存服务 [^3] 2. **资源敏感应用**:移动端应用的核心管理器 3. **依赖注入框架**:Spring容器中的Bean管理 [^2] 4. **配置管理类**:全局配置参数的统一访问点 5. **缓存系统**:内存缓存的共享访问实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值