一、单例模式概述

1.1、什么是单例模式

单例模式是软件开发中常用的一种创建型的设计模式,核心目标是确保一个类在一个系统中只有一个实例。

1.2、单例模式使用场景

  1. 日志记录器(Logger)
  2. 线程池(ThreadPool)
  3. 配置管理器(Configuration Manager)
  4. 缓存(Cache)
  5. 数据库连接池

1.3、单例模式要点

  1. 私有化构造方法 防止外部程序new 出类的实例
  2. 私有的静态类实例变量
  3. 公共的返回静态类实例的方法

二、单例模式的创建

1.1、饿汉式创建单例模式

优点 

线程安全

实现简单

缺点

类加载就创建,可能造成资源浪费

/**
 * 饿汉式单例模式
 *
 * @author LS
 * @version 1.0
 * @createDate 2025/8/17 18:50
 **/
public class Singleton01 {

    private  static final Singleton01 instance =new Singleton01();

    private Singleton01() {
    }

    public static Singleton01 getInstance() {
        return instance;
    }

}

1.2、懒汉式创建单例模式

优点

延迟加载,不会造成资源浪费

缺点

多线程环境下可能创建多个实例-不推荐使用

/**
 * 懒汉式创建单例模式
 *
 * @author LS
 * @version 1.0
 * @createDate 2025/8/17 19:02
 **/
public class Singleton02 {
    private static Singleton02 instance;
    private Singleton02(){};

    public static Singleton02 getInstance() {
        if (instance==null){
            instance=new Singleton02();
        }
        return instance;
    }
}

1.3、懒汉式+同步方法

优点

线程安全

避免资源浪费

缺点

性能较差

/**
 * 懒汉式 + 同步方法(线程安全但性能差)
 *
 * @author LS
 * @version 1.0
 * @createDate 2025/8/17 19:07
 **/
public class Singleton03 {
    private static Singleton03 instance;
    private Singleton03(){};
    public static synchronized Singleton03 getInstance(){
        if (instance==null){
            instance=new Singleton03();
        }
        return instance;
    }
}

1.4、双重检查锁定(Double-Checked Locking)创建

优点 推荐使用

线程安全、延时加载、性能高

/**
 * 双重检查锁定 创建单例模式
 *
 * @author LS
 * @version 1.0
 * @createDate 2025/8/17 19:15
 **/
public class Singleton04 {
    // 使用 volatile 防止指令重排序
    private static volatile Singleton04 instance;
    private Singleton04(){}
    public static Singleton04 getInstance(){
        if (instance==null){
            synchronized (Singleton.class){
                if (instance==null){
                    instance=new Singleton04();
                }
            }
        }
        return instance;
    }
}

1.5、枚举类创建单例模式

 优点:

天生线程安全

防止反射攻击(private 构造函数可被反射破坏,但枚举不行)

防止反序列化创建新实例

代码极简

Joshua Bloch(《Effective Java》作者)推荐使用枚举实现单例。

/**
 * 枚举类创建单例模式
 *
 * @author LS
 * @version 1.0
 * @createDate 2025/8/2 20:29
 **/
public enum Singleton {

    INSTANCE;

    public void doSomething() {
        System.out.println("单例测试");
    }
}

单例模式的创建还有好多,掌握上面几种在开发和面试中基本够了,接下来分享Spring中使用单例模式的案例。

三、经典的单例模式使用案例之Spring单例模式分析

3.1、Spring 单例的核心实现机制

     核心类:DefaultSingletonBeanRegistry

    核心数据结构:ConcurrentHashMap<String, Object>

  • 这个 Map 就是 Spring 单例池(俗称“单例缓存”)。
  • 所有创建好的单例 Bean 都会被放入这个 Map 中,key 是 beanName,value 是 Bean 实例。
  • 下次获取时直接从 Map 中取,保证唯一性。

3.2、单例创建流程(简化版)

当调用 applicationContext.getBean("xxx") 时,Spring 内部执行如下逻辑:

// 伪代码,源自 DefaultSingletonBeanRegistry.getSingleton()
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    // 1. 先尝试从缓存中获取
    Object singletonObject = this.singletonObjects.get(beanName);
    
    if (singletonObject == null) {
        // 2. 同步块,防止并发创建
        synchronized (this.singletonObjects) {
            // 再次检查(Double-Check)
            singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                // 3. 使用工厂创建实例
                singletonObject = singletonFactory.getObject();
                
                // 4. 创建完成后放入缓存
                this.singletonObjects.put(beanName, singletonObject);
            }
        }
    }
    return singletonObject;
}

这正是 “双重检查 + 缓存” 的典型单例实现!

四、结语

单例模式看似简单,但背后涉及类加载机制、线程安全、JVM 内存模型、反射、序列化等多个 Java 核心知识点。掌握它,不仅能写出高质量代码,还能在面试中脱颖而出。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐