单例模式特点:1、构造器私有! !!2、私有化静态属性 3、提供一个静态!!方法获取
饿汉加载
饿汉加载线程安全,不用考虑线程安全问题 -----because 当调用Singleton.getInstance静态方法时,加载了Singleton1类,同时在类加载时也触发了Singleton1的实例化(singleton1),所以return singleton1 是线程安全的。so 饿汉加载的getInstance方法不需要synchronize 同步。
/**
*
* 饿汉加载 lazyLoad
*/
public class Singleton1 {
private static Singleton1 singleton1 = new Singleton1();
private Singleton1(){}
public static Singleton1 getInstance() {
return singleton1;
}
}
懒汉加载
懒汉加载会出现的问题是,在==null之后的判断中,线程不安全
/**
* 懒汉加载
*/
public class Singleton2 {
private static Singleton2 singleton2;
private Singleton2(){}
public static Singleton2 getInstance() {
if (singleton2 == null) {
singleton2 = new Singleton2();
}
return singleton2;
}
}
静态内部类
既实现了懒加载,又保证了线程安全
懒加载是由于只有调用getInstance方法,才会触发SingletonInner的实例化
线程安全是因为singletonInner是在SingletonInner类加载时创建的,线程安全
/**
* 静态内部类实现单例
*/
public class Singleton3 {
private static class SingletonInner {
private final static SingletonInner singletonInner = new SingletonInner();
}
private Singleton3(){}
public SingletonInner getInstance() {
return SingletonInner.singletonInner;
}
}
通过反射破坏饿汉单例模式
Singleton1 s1 = Singleton1.getInstance();
Constructor<Singleton1> constructor = Singleton1.class.getDeclaredConstructor();
constructor.setAccessible(true);
Singleton1 s2 = constructor.newInstance();
通过反射获得单例类的构造函数,由于该构造函数是private的,通过setAccessible(true)指示反射的对象在使用时应该访问权限限制,使得私有的构造函数能够被访问,这样使得饿汉单例模式失效。