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 关键字确保多线程环境下的可见性,创建对象时会有一个引用赋值和初始化的重排序问题。
final 和 volatile 不能同时使用
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!
}
}
本文来自博客园,作者:chendsome,转载请注明原文链接:https://www.cnblogs.com/chendsome/p/18718432

浙公网安备 33010602011771号