首页
学习
活动
专区
圈层
工具
发布

在Java中编写单例的不同方法

在Java中实现单例模式有多种方法,每种方法在线程安全性能初始化时机上有所不同。以下是常见的实现方式及其特点:

1. 饿汉式(Eager Initialization)

特点:类加载时立即初始化,线程安全但可能浪费资源。

代码语言:txt
复制
public class Singleton {
    private static final Singleton INSTANCE = new Singleton();
    
    private Singleton() {} // 私有构造
    
    public static Singleton getInstance() {
        return INSTANCE;
    }
}

优势:简单、线程安全。 缺点:即使未使用也会创建实例,占用内存。

2. 懒汉式(Lazy Initialization)

特点:延迟初始化,但非线程安全。

代码语言:txt
复制
public class Singleton {
    private static Singleton instance;
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton(); // 多线程下可能重复创建
        }
        return instance;
    }
}

改进(同步方法)

代码语言:txt
复制
public static synchronized Singleton getInstance() {
    if (instance == null) {
        instance = new Singleton();
    }
    return instance;
}

缺点:同步方法性能较差。

3. 双重检查锁(Double-Checked Locking)

特点:延迟初始化 + 线程安全 + 高效。

代码语言:txt
复制
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 防止指令重排序(避免半初始化对象)。
  • 第一次检查避免不必要的同步。

4. 静态内部类(Holder Pattern)

特点:延迟加载 + 线程安全 + 无同步开销。

代码语言:txt
复制
public class Singleton {
    private Singleton() {}
    
    private static class Holder {
        static final Singleton INSTANCE = new Singleton();
    }
    
    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }
}

原理:利用类加载机制保证线程安全,Holder类仅在调用getInstance()时加载。

5. 枚举(Enum)

特点:最简洁的线程安全实现,防止反射攻击。

代码语言:txt
复制
public enum Singleton {
    INSTANCE;
    
    public void doSomething() {
        // 业务方法
    }
}

优势

  • 天然线程安全。
  • 自动处理序列化和反射问题(推荐方式)。

6. ThreadLocal 单例

特点:线程内单例,不同线程不同实例。

代码语言:txt
复制
public class ThreadLocalSingleton {
    private static final ThreadLocal<ThreadLocalSingleton> instance =
        ThreadLocal.withInitial(ThreadLocalSingleton::new);
    
    private ThreadLocalSingleton() {}
    
    public static ThreadLocalSingleton getInstance() {
        return instance.get();
    }
}

应用场景:需要线程隔离的单例(如数据库连接)。

常见问题与解决

  1. 反射破坏单例
    • 解决方法:在私有构造器中检查实例是否已存在(非枚举方式)。
  • 序列化破坏单例
    • 解决方法:实现readResolve()方法返回现有实例。
  • 指令重排序问题
    • 解决方法:使用volatile(如双重检查锁)。

总结

  • 推荐:枚举(简单安全)或静态内部类(性能优)。
  • 慎用:懒汉式(需处理线程安全)。
  • 特殊需求ThreadLocal(线程隔离)、双重检查锁(高性能延迟加载)。
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

没有搜到相关的文章

领券