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