1.实现一:
public class Singleton implements Serializable {
private Singleton(){}
private static final Singleton INSTANCE = new Singleton();
public static Singleton getInstance(){
return INSTANCE;
}
}
1.1、为什么加final
怕子类覆盖父类里的方法
1.2、如果实现了序列化接口,还要做什么来防止反序列化破坏单例
反序列化也会生成新的对象,如果与单例模式中想要维护对象不同,就相当于破坏了单例。
解决方法
public Object readResovle(){
return INSTANCE;
}
如果反序列化发现readResovle返回了对象,就会把其返回的对象当做结果。
1.3、为什么设置为私有?是否能防止反射创建新的实例?
private Singleton(){}
防止多次创建对象,不能防止反射。
1.4、这样初始化是否保证单例对象创建时的线程安全?
private static final Singleton INSTANCE = new Singleton();
没有线程安全问题,静态成员变量的初始化在类加载的时候完成,由jvm保证了线程的安全。
1.5、为什么提供静态方法而不是直接将INSTANCE设置为public
提供更好的封装性,可以提供懒惰的初始化;可以提供泛型的支持;对创建单例变量有更好的控制。
2.实现二
enum singleton{
INSATCNE;
}
2.1 枚举单例是如何限制实例个数的
由枚举控制,是单实例的。
2.2 枚举单例在创建时是否有并发问题
没有。因为它也是静态成员变量。
2.3 枚举能否被反射破坏单例
不能用反射破坏。拿不到构造方法,不能实现反射。
2.4 枚举单例能否被反序列化破坏单例
枚举在实现的时候就继承了序列化的接口,不能被破坏。
2.5枚举单例属于懒汉式还是饿汉式
饿汉式的
2.6 枚举单例如果希望加入一些单例创建时的初始化逻辑该如何做
添加构造方法,实现初始化。
实现3
class Singleton {
//1.构造器私有化,外部不能new
private Singleton(){}
//2.本类内部创建对象实例
private static Singleton instance;
//提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题
//即懒汉式
public static synchronized Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
public static synchronized Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
在上述地方会出现效率低下,第一次的访问的时候,通过同步锁创建对象,但是对象创建了之后,可以不通过同步锁访问了,同步锁的范围太大了。
4、实现4
class Singleton {
//1.构造器私有化,外部不能new
private Singleton(){}
//2.本类内部创建对象实例
private static volatile Singleton instance;
//提供一个静态的公有方法,当使用到该方法时,才去创建instance
//即懒汉式
public static Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
4.1 为什么要加volatile?
指令可能会重排序,同步代码块可能先赋值,再去创建对象,同步代码块外面的对象可能会拿到不完整的对象。
4.2 对比实现3,说出这样做的意义
第一次调用的话,会继续创建对象,但是第二、第三次调用,可以直接判断,不用再通过同步代码了,提升了效率。
4.3 为什么还要在同步代码块中加是否为空的判断
为了防止首次多线程的调用,如果同时有两个线程都进到代码块时,可以防止多次创建对象。
5、实现五
class Singleton {
private Singleton(){}
private static class SingletonInstance{
private static final Singleton INSTANCE = new Singleton();
}
//提供一个静态的公有方法,当使用到该方法时,才去创建instance
//即懒汉式
public static Singleton getInstance(){
return SingletonInstance.INSTANCE;
}
}
利用静态内部类特点实现延迟加载,效率高