单例模式的定义

单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供全局访问点。适用于需要控制资源(如数据库连接、线程池)或共享配置的场景。


单例模式的实现方式

懒汉式(线程不安全)

在首次调用时创建实例,适合非多线程环境。

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

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

懒汉式(线程安全)

通过同步方法保证线程安全,但性能较低。

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

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

双重检查锁(DCL)

减少同步开销,兼顾线程安全和性能。

public class Singleton {
    private static volatile Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

静态内部类

利用类加载机制保证线程安全,且延迟初始化。

public class Singleton {
    private Singleton() {}

    private static class Holder {
        static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }
}

枚举单例

简洁且防反射攻击,天然线程安全。

public enum Singleton {
    INSTANCE;
    // 添加其他方法
}


单例模式的应用场景

  • 资源共享:如数据库连接池、日志管理器。
  • 配置管理:全局配置对象的唯一访问点。
  • 控制资源:如线程池、缓存系统。

注意事项

  • 线程安全:多线程环境下需选择线程安全的实现方式。
  • 反射攻击:除枚举外,其他方式可能被反射破坏单例,需额外防护。
  • 序列化:若单例类可序列化,需实现readResolve()方法防止反序列化生成新实例。

通过合理选择实现方式,单例模式能有效管理全局唯一资源。

Java 单例模式实现及说明

单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供全局访问点。以下是几种常见的实现方式及其说明。

饿汉式单例(线程安全)
public class Singleton {
    // 类加载时直接初始化实例
    private static final Singleton instance = new Singleton();

    // 私有构造方法防止外部实例化
    private Singleton() {}

    // 提供全局访问点
    public static Singleton getInstance() {
        return instance;
    }
}

  • 特点:在类加载时创建实例,线程安全,但可能造成资源浪费(即使未使用也会加载实例)。
  • 适用场景:实例占用资源较小,且程序启动时就需要初始化。
懒汉式单例(线程不安全)
public class Singleton {
    private static Singleton instance;

    private Singleton() {}

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

  • 特点:延迟初始化,但多线程环境下可能创建多个实例。
  • 改进:可通过 synchronized 加锁解决线程安全问题,但会降低性能。
双重检查锁(线程安全)
public class Singleton {
    private static volatile Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

  • 特点:延迟初始化,线程安全,且减少锁的粒度提升性能。
  • 关键点volatile 防止指令重排序,避免未完全初始化的对象被引用。
静态内部类实现(线程安全)
public class Singleton {
    private Singleton() {}

    private static class Holder {
        private static final Singleton instance = new Singleton();
    }

    public static Singleton getInstance() {
        return Holder.instance;
    }
}

  • 特点:利用类加载机制保证线程安全,延迟初始化,且无需同步开销。
  • 原理:静态内部类在首次调用 getInstance() 时才会加载,触发实例初始化。
枚举单例(线程安全)
public enum Singleton {
    INSTANCE;

    public void doSomething() {
        // 实例方法
    }
}

  • 特点:简洁,线程安全,且防止反序列化破坏单例。
  • 优势:枚举实例由 JVM 保证唯一性,无需额外代码处理。

选择建议

  • 推荐:优先使用 枚举单例静态内部类 实现,兼顾线程安全和简洁性。
  • 注意:避免通过反射或序列化破坏单例,枚举类型天然支持防护。
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐