MST

星途 面试题库

面试题:Java单例模式的线程安全实现方式及对比

在Java中,单例模式有多种实现线程安全的方式,请详细描述至少两种实现方式,并分析它们在性能、资源占用等方面的优缺点。
15.4万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

饿汉式

  1. 代码实现
public class Singleton {
    private static final Singleton INSTANCE = new Singleton();
    private Singleton() {}
    public static Singleton getInstance() {
        return INSTANCE;
    }
}
  1. 优点
    • 线程安全,因为类加载时就创建实例,不存在多线程创建实例的问题。
    • 实现简单,代码量少。
  2. 缺点
    • 资源浪费,不管是否使用这个单例,类加载时就会创建实例。
    • 不支持延迟加载,如果单例创建开销大且长时间不用,会造成性能浪费。

静态内部类方式

  1. 代码实现
public class Singleton {
    private Singleton() {}
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
  1. 优点
    • 线程安全,利用了类加载机制保证实例的唯一性。
    • 支持延迟加载,只有在调用getInstance()方法时,才会加载SingletonHolder类并创建实例。
    • 性能较好,没有额外的同步开销。
  2. 缺点
    • 相比饿汉式实现稍微复杂一点。

双重检查锁(DCL)方式

  1. 代码实现
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;
    }
}
  1. 优点
    • 支持延迟加载,提高了资源利用率。
    • 性能较高,只有第一次创建实例时会有同步开销,后续调用直接返回实例。
  2. 缺点
    • 实现复杂,需要注意volatile关键字的使用,防止指令重排导致的空指针异常。
    • 在高并发场景下,synchronized同步块会有一定的性能开销,虽然相比其他同步方式已经优化。