Java单例模式:饿汉式VS懒汉式

概要

单例模式是 Java 设计模式中最常用的模式之一,确保一个类只有一个实例,并提供一个全局访问点。下面结合您提供的代码,详细讲解饿汉式和懒汉式单例模式的区别与实现。

饿汉式单例模式(Eager Initialization)

特点

  • 类加载时就创建实例(急切初始化)
  • 线程安全(由JVM类加载机制保证)
  • 简单直接,但可能造成资源浪费(即使不用也会创建实例)

代码实现

public class Singleton {
    // 类加载时就初始化(静态变量)
    private static Singleton s = new Singleton();
    
    // 私有构造方法
    private Singleton(){}
    
    // 公开的静态获取方法
    public static Singleton get(){
        return s;
    }
}

测试验证

Singleton s1 = Singleton.get();
Singleton s2 = Singleton.get();
System.out.println(s1 == s2); // 输出 true,是同一个对象

优点

  • 实现简单
  • 线程安全(无需额外同步措施)

缺点

  • 类加载时就初始化,可能浪费资源
  • 如果初始化过程复杂,会拖慢应用启动速度

懒汉式单例模式(Lazy Initialization)

特点

  • 延迟初始化(第一次使用时才创建实例)
  • 节省资源
  • 基础实现线程不安全,需要额外处理

基础实现(非线程安全)

public class Singleton {
    // 声明但不初始化(null)
    private static Singleton s;
    
    private Singleton(){}
    
    public static Singleton get() {
        if(s == null) { // 第一次调用时创建
            s = new Singleton();
        }
        return s;
    }
}

测试验证

Singleton s1 = Singleton.get();
Singleton s2 = Singleton.get();
System.out.println(s1 == s2); // 输出 true

线程安全问题

基础懒汉式实现在多线程环境下可能创建多个实例,需要改进:

解决方案1:同步方法(效率低)

public static synchronized Singleton get() {
    if(s == null) {
        s = new Singleton();
    }
    return s;
}

解决方案2:双重检查锁定(推荐)

private volatile static Singleton s;

public static Singleton get() {
    if(s == null) { // 第一次检查
        synchronized(Singleton.class) {
            if(s == null) { // 第二次检查
                s = new Singleton();
            }
        }
    }
    return s;
}

优点

  • 延迟加载,节省资源
  • 适合初始化耗时的对象

缺点

  • 实现比饿汉式复杂
  • 需要考虑线程安全问题

两种模式对比

特性 饿汉式 懒汉式
初始化时机 类加载时 第一次调用时
线程安全 天然安全 需要额外处理
资源利用 可能浪费 按需使用
实现复杂度 简单 较复杂
性能 类加载稍慢 首次调用稍慢
适用场景 初始化简单、使用频繁 初始化复杂、不常用

你可能感兴趣的:(Java单例模式:饿汉式VS懒汉式)