MST

星途 面试题库

面试题:Java中常见的反模式及优化思路

在Java开发中,单例模式如果实现不当可能会出现哪些反模式?针对这些反模式,应该如何优化以保障软件质量?
49.4万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

可能出现的反模式

  1. 懒汉式单例未考虑线程安全
    • 问题描述:懒汉式单例在多线程环境下,如果多个线程同时调用 getInstance 方法,可能会创建多个实例,破坏单例模式。
    • 示例代码
public class LazySingleton {
    private static LazySingleton instance;

    private LazySingleton() {}

    public static LazySingleton getInstance() {
        if (instance == null) {
            instance = new LazySingleton();
        }
        return instance;
    }
}
  1. 饿汉式单例可能造成资源浪费
    • 问题描述:饿汉式单例在类加载时就创建实例,即使该实例在整个应用生命周期中可能永远不会被使用,从而造成资源浪费。
    • 示例代码
public class EagerSingleton {
    private static final EagerSingleton instance = new EagerSingleton();

    private EagerSingleton() {}

    public static EagerSingleton getInstance() {
        return instance;
    }
}
  1. 双重检查锁定(DCL)的早期实现存在问题
    • 问题描述:早期的双重检查锁定实现中,由于指令重排,可能导致在 instance 还未完全初始化时就被其他线程获取,从而引发空指针异常。
    • 示例代码
public class DoubleCheckedLockingSingleton {
    private static DoubleCheckedLockingSingleton instance;

    private DoubleCheckedLockingSingleton() {}

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

优化方式

  1. 懒汉式单例优化为线程安全
    • 使用 synchronized 关键字:在 getInstance 方法上添加 synchronized 关键字,确保同一时间只有一个线程能进入方法创建实例。
    • 示例代码
public class ThreadSafeLazySingleton {
    private static ThreadSafeLazySingleton instance;

    private ThreadSafeLazySingleton() {}

    public static synchronized ThreadSafeLazySingleton getInstance() {
        if (instance == null) {
            instance = new ThreadSafeLazySingleton();
        }
        return instance;
    }
}
- **使用静态内部类**:利用类加载机制实现延迟加载且线程安全。
- **示例代码**:
public class StaticInnerClassSingleton {
    private StaticInnerClassSingleton() {}

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

    public static StaticInnerClassSingleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
  1. 饿汉式单例优化资源浪费问题
    • 改为静态内部类方式:如上述静态内部类单例实现,在需要使用实例时才加载内部类并创建实例。
  2. 双重检查锁定优化
    • 使用 volatile 关键字:给 instance 变量添加 volatile 修饰符,防止指令重排。
    • 示例代码
public class SafeDoubleCheckedLockingSingleton {
    private volatile static SafeDoubleCheckedLockingSingleton instance;

    private SafeDoubleCheckedLockingSingleton() {}

    public static SafeDoubleCheckedLockingSingleton getInstance() {
        if (instance == null) {
            synchronized (SafeDoubleCheckedLockingSingleton.class) {
                if (instance == null) {
                    instance = new SafeDoubleCheckedLockingSingleton();
                }
            }
        }
        return instance;
    }
}
  1. 使用枚举实现单例
    • 描述:枚举类型天然线程安全,并且在类加载时就被初始化,同时防止反射和序列化破坏单例。
    • 示例代码
public enum EnumSingleton {
    INSTANCE;

    // 可以添加业务方法
    public void doSomething() {
        System.out.println("执行单例的业务方法");
    }
}