念两句诗

单例模式

2024-08-22 浏览 面试必备 467字 2 min read

饿汉式单例

饿汉式单例在类加载时就创建实例,因此是线程安全的。

public class EagerSingleton{
    private static final EagerSingleton INSTANCE = new EagerSingleton();
    private EagerSingleton(){
        //私有构造器
    }
    public static EagerSingleton getInstance(){
        return INSTANCE;
    }
}

懒汉式单例

懒汉式单例在第一次调用getInstance方法时创建实例。这种方式不是线程安全的。在多线程环境下,如果多个线程同时访问getInstance方法并且instancenull,那么多个线程可能会同时通过if (instance == null)这个检查,导致多个线程同时创建实例,这就违反了单例模式的初衷,导致创建了多个实例。

public class LazySingleton{
    private static LazySingleton instance;
    private LazySingleton(){
    //私有构造器
    }
    //多线程下,由于多个线程访问
    public static LazySingleton getInstance(){
        if(instance ==null){
            instance = new LazySingleton();
        }
        return instance;
    }
}

线程安全的懒汉式单例

通过同步getInstance方法来确保线程安全,但这种方式性能较差,因为每次访问都需要同步。

public class SynchronizedLazySingleton{
    private static SynchronizedLazySingleton instance;
    private SynchronizedLazySingleton(){
        //私有构造器
    }
    public static synchronized SynchronizedLazySingleton getInstance(){
         if (instance == null) {
            instance = new SynchronizedLazySingleton();
        }
        return instance;
    }
}

双重检查锁

使用双重检查锁机制来确保线程安全,同时提高性能。

public class DoubleCheckedLockingSingleton{
    //使用volatile关键字
	private static volatile DoubleCheckedLockingSingleton instance;
    private DoubleCheckedLockingSingleton(){
        //私有构造器
    }
    public static DoubleCheckedLockingSingleton getInstance(){
        if(instance == null){
            synchronized(DoubleCheckedLockingSingleton.class){
                if(instance ==null){
                    instance =  new DoubleCheckedLockingSingleton();
                }
            }
        }
        return instance;
    }
}

静态内部类

Java虚拟机在加载外部类时,并不会立即加载静态内部类,只有在第一次访问静态内部类的成员时,才会加载该内部类。由于类加载过程是线程安全的,JVM会保证一个类的<clinit>()方法在多线程环境下被正确地加锁和同步。

public class BillPughSingle{
    private BillPughSingleton() {
        // 私有构造器
    }
    //使用静态内部类
    private static class SingletonHelper {
        private static final BillPughSingleton INSTANCE = new BillPughSingleton();
    }
    public static BillPughSingleton getInstance() {
        return SingletonHelper.INSTANCE;
    }
}
EOF