Java单例模式的实现

饿汉式

线程安全,由jvm类加载时初始化,保证线程安全

public class EagerSingleton {
    // static保证唯一,final保证不可变
    private static final EagerSingleton INSTANCE = new EagerSingleton();

    private EagerSingleton(){}

    public static EagerSingleton getInstance(){
        return INSTANCE;
    }
}

懒汉式

懒加载,线程不安全,因为实例化对象有个判断的过程,但是可以加个synchronized来保证线程安全。

public class LazySingleton {
    // 由于需要懒加载,不能使用final关键字,需要自己保证安全
    private static LazySingleton INSTANCE;

    private LazySingleton() {}

    // public static synchronized LazySingleton getInstance() {
    public static LazySingleton getInstance() {
        if(INSTANCE == null){
            INSTANCE = new LazySingleton();
        }
        return INSTANCE;
    }
}

双重检查锁

线程安全,使用 volatile 关键字确保多线程环境下的可见性,创建对象时会有一个引用赋值和初始化的重排序问题。
finalvolatile 不能同时使用

public class DoubleCheckSingleton {
    private static volatile DoubleCheckSingleton INSTANCE;

    private DoubleCheckSingleton() {}

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

静态内部类

既保证了线程安全,又是延迟加载。

  • 将单例实例放在静态内部类中:
    静态内部类在外部类加载时不会初始化,只有在调用 getInstance() 时才会加载并初始化静态内部类,从而实现延迟初始化。
  • 利用类加载机制保证线程安全:
    JVM 在加载类时会自动加锁,保证类加载过程的线程安全性,因此静态内部类的初始化是线程安全的。

静态内部类的特性

静态内部类是定义在另一个类内部的静态类。它有以下特点:

  • 静态内部类是独立于外部类的:
    静态内部类与外部类的实例无关,可以直接通过外部类名访问。
  • 静态内部类在加载时不会初始化:
    静态内部类只有在被主动使用时才会加载初始化
public class InnerSingleton {
    private InnerSingleton() {}

    private static class SingletonHolder {
        private static final InnerSingleton INSTANCE = new InnerSingleton();
    }

    public static InnerSingleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

枚举类

枚举单例的优势

  • 线程安全:
    枚举实例的创建由 JVM 保证线程安全,无需额外同步。
  • 防止反射破坏单例:
    枚举类的构造函数是私有的,且 JVM 禁止通过反射创建枚举实例。
  • 防止序列化破坏单例:
    枚举类的序列化和反序列化由 JVM 保证,不会创建新的实例。
  • 代码简洁:
    枚举单例的实现非常简单,只需几行代码。
public enum EnumSingleton {
    INSTANCE; // 单例实例

    // 可以添加其他方法和属性
    public void doSomething() {
        System.out.println("Singleton instance is doing something!");
    }
}

扩展一下

public enum Singleton {
    INSTANCE;

    private String name;

    // 可以添加方法
    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void doSomething() {
        System.out.println("Singleton instance is doing something!");
    }
}

使用示例:

public class Main {
    public static void main(String[] args) {
        Singleton instance = Singleton.INSTANCE;
        instance.setName("Singleton Example");
        System.out.println("Name: " + instance.getName()); // 输出: Name: Singleton Example
        instance.doSomething(); // 输出: Singleton instance is doing something!
    }
}
posted @ 2025-02-16 17:38  chendsome  阅读(42)  评论(0)    收藏  举报