作为23中设计模式中最简单的一种模式,网传有8中写法。我想说的是:会的多不如学的精,今天看了一个公众号推送的文章,上面直接说双重检查机制的单例是线程安全的。
首先,从大类上分:饿汉和懒汉。就是要不要延迟实例化的问题?
如果,你项目中的有配置类,构造类等,反正你迟早要用到,为了不出错,直接饿汉式就好了。写代码首先是安全,其次是性能,千万别学了点花把式就看不起基础的拳脚。
package learn.singleton;
public class Singleton1 {
private final static Singleton1 singleton1 = new Singleton1();
public static Singleton1 getSingleton1(){
return singleton1;
}
private Singleton1(){
}
}
//final关键字的语义,不用final可以不?
//这个看着简单,能否解释下,为啥线程安全?
//如果遇到使用反射创建对象时,这种是不是失效了?
//有没有一种没有线程安全问题,同时不害怕反射机制的单例?
package learn.singleton;
public class Singleton2 {
private volatile static Singleton2 singleton2 ;
public static Singleton2 getSingleton2(){
if(singleton2==null){
synchronized (Singleton2.class){
if(singleton2==null){
singleton2 = new Singleton2();
}
}
}
return singleton2;
}
private Singleton2(){
}
}
//双重检测锁,不使用volatile关键字修饰时,为啥是线程不安全的
//指令重排是什么?
//反射暴力破解时,怎么解决
package learn.singleton;
public class Singleton3 {
private Singleton3(){
}
public static class InnerSingleton3{
private final static Singleton3 singleton3 = new Singleton3();
public static Singleton3 getSingleton3() {
return singleton3;
}
}
}
//静态内部类的方式,其实和第一种一样都是饿汉式
package learn.singleton;
public enum Singleton4 {
INSTANCE;
public Singleton4 getInstance(){
return INSTANCE;
}
}
//最最推荐使用的,可以解决反射的问题和序列话的问题
//枚举类都是继承了Enum抽象类
//没有无参的构造方法
//只有一个俩个参数的构造方法,可是,当你使用反射
//newInstance的时候,会抛异常。
//Cannot reflectively create enum objects