单例模式(Singleton Pattern) 是最简单的设计模式之一,属于 创建型模式,旨在确保一个类只有一个实例,并提供一个全局访问点来访问这个实例。
单例模式的核心思想是确保某个类在整个应用程序中只能有一个实例,并提供一个全局的访问方法来获取该实例。
饿汉式单例在类加载时就立即创建好唯一实例。它的缺点是即使没有用到单例对象,也会在程序启动时就创建实例,可能会导致资源浪费。
public class Singleton {
// 创建静态实例,饿汉式
private static final Singleton instance = new Singleton();
// 私有构造函数,防止外部直接创建实例
private Singleton() {}
// 公共静态方法提供唯一实例
public static Singleton getInstance() {
return instance;
}
}优点:
缺点:
懒汉式单例在第一次需要时创建实例。它的缺点是在多线程环境下可能会出现线程安全问题,导致多个线程同时创建实例。
public class Singleton {
// 声明实例,初始为null
private static Singleton instance;
// 私有构造函数,防止外部直接创建实例
private Singleton() {}
// 公共静态方法提供唯一实例
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}优点:
缺点:
if (instance == null) 判断,从而创建多个实例,导致线程安全问题。为了解决懒汉式单例中的线程安全问题,双重检查锁定(DCL)通过在 getInstance() 方法中加入 synchronized 关键字进行控制,但只在实例为空时才加锁,提升性能。
public class Singleton {
// 声明实例,初始为null
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 关键字保证了内存的可见性,可以有效解决这个问题。静态内部类单例是最推荐的实现方式。它结合了懒加载和线程安全,并且性能优于双重检查锁定。其原理是利用 静态内部类 在 Java 中的类加载机制,确保实例只有在第一次被访问时才创建。
public class Singleton {
// 静态内部类实现单例
private static class SingletonHelper {
// 静态初始化器,JVM保证线程安全
private static final Singleton INSTANCE = new Singleton();
}
// 私有构造函数,防止外部直接创建实例
private Singleton() {}
// 公共静态方法提供唯一实例
public static Singleton getInstance() {
return SingletonHelper.INSTANCE;
}
}优点:
缺点:
枚举单例是单例模式的最佳实现方式,它是由 Joshua Bloch(《Effective Java》作者)推荐的。使用枚举类来实现单例模式不仅简洁,而且它能够防止反射和序列化攻击。
public enum Singleton {
INSTANCE;
// 可以添加其他方法
public void doSomething() {
System.out.println("Doing something...");
}
}优点:
缺点:
单例模式在多线程编程中非常有用,可以保证只有一个实例,且通过全局访问点访问该实例。实现时需要特别注意线程安全性,在 Java 中,推荐使用 静态内部类单例 或 枚举单例 来实现单例模式,二者提供了线程安全且高效的解决方案。
如果您有任何问题或建议,欢迎留言讨论。