//1.final修饰保证不能被子类继承,避免修改类行为
public final class Singleton1 implements Serializable {
//2.一定要私有化构造函数,避免通过构造函数新建对象,但还是可以通过反射创建
private Singleton1(){}
//3.实例采用static和final修饰,类加载时就完成了初始化,所以能保证对象的唯一性,
// 同时还可以保证线程安全,不过一开始就创建了对象,不能达到懒加载的目的
private static final Singleton1 instance = new Singleton1();
public static Singleton1 getInstance(){
return instance;
}
//4.该方法用来保证可序列化对象,反序列化后还是单例的
public Singleton1 readResolve(){
return instance;
}
}
2.DCL
//1.DCL双重检查模式,既保证了懒加载,还保证了线程间的安全
public final class Singleton2 {
private Singleton2(){}
//2.这里的volatile修饰符是起到禁止重排序的目的,如果没有该修饰符,
// 在字节码层面,线程A可以将未实例化的对象赋值给静态变量,然后线程B就能得到这个未实例化的静态变量,
// 添加volatile修饰符就是为了保证静态变量必须先经过实例化,同时达到线程可见的目的。
private volatile static Singleton2 instance = null;
public static Singleton2 getInstance(){
//3.第一重检查是为了避免所有线程都去获取锁,如果对象已经被创建,就可以直接返回
if(instance == null){
synchronized (Singleton2.class){
//4.第二重锁是避免多线程环境下,可能有多个线程正在竞争锁,从而会创建多个实例
if(instance == null){
instance = new Singleton2();
}
}
}
return instance;
}
}
3.静态内部类
//1.静态内部类的形式创建单例,满足懒加载和线程安全
public final class Singleton3 {
private Singleton3(){}
//2.静态内部类会在第一次使用到的时候创建,达到懒加载的效果
private static class Instance{
private static final Singleton3 instance = new Singleton3();
}
public static Singleton3 getInstance(){
return Instance.instance;
}
}