线程安全的单例类
单例模式中,有两种实现,一种是饥饿模式,另一种是懒汉模式。
饥饿模式的实现:
public final class EagerSingleton { private static EagerSingleton instance = new EagerSingleton(); private EagerSingleton(){ } public static EagerSingleton getSingleInstance(){ return instance; } } 优点:线程安全
缺点:未使用该对象的时候,已经加载到了内存,但对象很大的时候是一种浪费
懒汉模式的基本实现:
public final class LazySingleton { private static LazySingleton instance = null; private LazySingleton(){ } public static LazySingleton getSingleInstance(){ if(null == instance ) { instance = new LazySingleton();}eturn instance; } } 优点:延迟加载,按需分配内存
缺点:线程不安全,如果两个线程同时第一次访问getInstance方法,则会生成两份实例。
为了解决懒汉模式的线程安全问题,第一种解决方法是在getInstance方法前加入synchronized修饰。
public final class LazySingleton { private static LazySingleton instance = null; private LazySingleton(){ } public static synchronized LazySingleton getSingleInstance(){ if(null == instance ) { instance = new LazySingleton();}eturn instance; } } 第一种方法可以解决线程安全问题,但使用synchronized同步必将降低性能,所以可以考虑将同步的粒度降低,所以有了第二种解决方法。
public final class DoubleCheckedSingleton { private static DoubleCheckedSingleton instance = null; private DoubleCheckedSingleton(){ } public static DoubleCheckedSingleton getSingleInstance(){ if(instance == null ) { Synchronized(DoubleCheckedSingleton.class){ if(instance == null){ instance = new DoubleCheckedSingleton(); } }}return instance; } } 第二种解决方法,实现了线程安全,同时也将同步的粒度降低到代码块中,提高了性能。但第二种解决方法是用双重检查锁来实现,这种做法是不推荐使用的。
那么就有了第三种解决方法,使用内部类来延迟加载,在类的加载过程中会保证线程的安全。
public class Singleton { private static class SingletonHolder { public final static Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; } }