还停留在懒汉式和饿汉式?这几种单例实现,让你代码更专业、更安全。

21 阅读3分钟

饿汉式

/**
 * 饿汉式 - 类加载时初始化
 * 优点:实现简单,线程安全
 * 缺点:不是懒加载,占用内存
 */
public class EagerSingleton {
    // 1. 静态常量,类加载时创建实例
    private static final EagerSingleton INSTANCE = new EagerSingleton();
    
    // 2. 私有构造器
    private EagerSingleton() {
        // 防止反射攻击
        if (INSTANCE != null) {
            throw new RuntimeException("Singleton instance already exists!");
        }
        System.out.println("EagerSingleton created");
    }
    
    // 3. 全局访问点
    public static EagerSingleton getInstance() {
        return INSTANCE;
    }
}

懒汉式-同步方法

/**
 * 懒汉式 - 同步方法
 * 优点:线程安全,延迟加载
 * 缺点:每次获取实例都要同步,性能差
 */
public class LazySyncSingleton {
    private static LazySyncSingleton instance;
    
    private LazySyncSingleton() {
        System.out.println("LazySyncSingleton created");
    }
    
    // synchronized 方法,线程安全但性能差
    public static synchronized LazySyncSingleton getInstance() {
        if (instance == null) {
            instance = new LazySyncSingleton();
        }
        return instance;
    }
}

懒汉式-双重检查锁

/**
 * 双重检查锁 - JDK 1.5+
 * 优点:线程安全,延迟加载,性能好
 * 缺点:实现复杂,早期JDK有问题
 */
public class DoubleCheckedSingleton {
    // volatile 防止指令重排序,保证可见性
    private static volatile DoubleCheckedSingleton instance;
    
    private DoubleCheckedSingleton() {
        System.out.println("DoubleCheckedSingleton created");
    }
    
    public static DoubleCheckedSingleton getInstance() {
        // 第一次检查,避免不必要的同步
        if (instance == null) {
            synchronized (DoubleCheckedSingleton.class) {
                // 第二次检查,防止多个线程同时通过第一次检查
                if (instance == null) {
                    // 1. 分配内存空间
                    // 2. 初始化对象
                    // 3. 设置instance指向内存空间
                    // volatile防止2和3重排序
                    instance = new DoubleCheckedSingleton();
                }
            }
        }
        return instance;
    }
}

静态内部类

/**
 * 静态内部类 - 推荐使用
 * 优点:线程安全,延迟加载,性能好
 * 缺点:不能传参
 */
public class InnerClassSingleton {
    private InnerClassSingleton() {
        System.out.println("InnerClassSingleton created");
    }
    
    // 静态内部类,JVM保证类加载的线程安全
    //内部类只有在使用时才会被加载 并且只加载一次
    private static class SingletonHolder {
        private static final InnerClassSingleton INSTANCE = new InnerClassSingleton();
    }
    
    public static InnerClassSingleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

枚举

/**
 * 枚举 - 《Effective Java》推荐
 * 优点:线程安全,防反射,防序列化
 * 缺点:不是懒加载
 */
public enum EnumSingleton {
    INSTANCE;
    
    // 可以添加方法
    public void doSomething() {
        System.out.println("EnumSingleton doing something");
    }
    
    // 可以添加字段
    private String data = "default";
    
    public String getData() {
        return data;
    }
    
    public void setData(String data) {
        this.data = data;
    }
}

ThreadLocal单例

/**
 * ThreadLocal 单例 - 线程内单例
 * 优点:线程安全,延迟加载
 * 缺点:不是全局单例,每个线程有自己的实例
 */
public class ThreadLocalSingleton {
    private static final ThreadLocal<ThreadLocalSingleton> threadLocal =
        ThreadLocal.withInitial(ThreadLocalSingleton::new);
    
    private ThreadLocalSingleton() {
        System.out.println("ThreadLocalSingleton created for thread: " 
            + Thread.currentThread().getName());
    }
    
    public static ThreadLocalSingleton getInstance() {
        return threadLocal.get();
    }
    
    // 使用示例
    public static void main(String[] args) {
        // 每个线程获取的是自己的实例
        new Thread(() -> {
            ThreadLocalSingleton instance1 = ThreadLocalSingleton.getInstance();
            ThreadLocalSingleton instance2 = ThreadLocalSingleton.getInstance();
            System.out.println(instance1 == instance2); // true
        }).start();
    }
}

CAS无锁实现

/**
 * CAS 单例 - 无锁实现
 * 优点:线程安全,无锁高性能
 * 缺点:实现复杂,可能多次创建但只保留一个
 */
import java.util.concurrent.atomic.AtomicReference;

public class CASSingleton {
    private static final AtomicReference<CASSingleton> INSTANCE = 
        new AtomicReference<>();
    
    private CASSingleton() {
        System.out.println("CASSingleton created");
    }
    
    public static CASSingleton getInstance() {
        while (true) {
            CASSingleton instance = INSTANCE.get();
            if (instance != null) {
                return instance;
            }
            
            instance = new CASSingleton();
            if (INSTANCE.compareAndSet(null, instance)) {
                return instance;
            }
            // 如果设置失败,说明其他线程已经设置了,重试
        }
    }
}

容器式单例

/**
 * 容器式单例 - Spring 风格
 * 优点:统一管理,可扩展
 * 缺点:非线程安全,需要额外同步
 */
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ContainerSingleton {
    private static final Map<String, Object> BEANS = 
        new ConcurrentHashMap<>();
    
    private ContainerSingleton() {}
    
    // 注册单例
    public static void register(String name, Object instance) {
        if (BEANS.containsKey(name)) {
            throw new RuntimeException("Bean already exists: " + name);
        }
        BEANS.put(name, instance);
    }
    
    // 获取单例
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
        return (T) BEANS.get(name);
    }
    
    // 使用示例
    public static void main(String[] args) {
        ContainerSingleton.register("service", new ServiceImpl());
        Service service = ContainerSingleton.getBean("service");
    }
}

选择建议

  1. 简单场景,不考虑延迟加载- -> 枚举
  2. 需要延迟加载,简单安全 --> 静态内部类
  3. 高性能要求,需要延迟加载 --> 懒汉式-双重检查锁
  4. 需要防反射、序列化攻击 --> 枚举
  5. 线程隔离 --> ThreadLocal
  6. Spring 容器管理 → 使用 @Component + @Scope("singleton")
  7. 需要传递参数 --> 静态内部类+初始化参数