// 类加final防止子类覆盖方法 破坏单例性质
public final class Singleton1 implements Serializable {
// 构造方法私有 但仍可以通过反射创建对象
private Singleton1() {}
// 类加载时初始化 由JVM保证线程安全(立即加载)
private static final Singleton1 INSTANCE = new Singleton1();
public static Singleton1 getInstance() {
return INSTANCE;
}
// 防止反序列化破坏单例
private Object readResolve() {
return INSTANCE;
}
}
/**
* 枚举类实现单例 无法用反射和反序列化破坏单例
*/
public enum Singleton2 {
// 本质上时枚举类的静态成员变量(立即加载) public static final ...
INSTANCE;
}
// 懒加载
public final class Singleton3 {
private Singleton3() {}
private static Singleton3 INSTANCE;
// 由锁(锁对象为Singleton3.class)来保证原子性和可见性
// 缺点是之后每次获取对象时都需要进行同步
public static synchronized Singleton3 getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton3();
}
return INSTANCE;
}
}
// DCL 懒加载
public final class Singleton4 {
private Singleton4() {}
private static volatile Singleton4 INSTANCE;
// 加锁只存在于第一次创建单例对象时 之后的获取都不用加锁
public static Singleton4 getInstance() {
if (INSTANCE != null) {
return INSTANCE;
}
// double check的原因时因为可能由多个线程都会到达这里
// 如:线程t1 t2 t1获得锁 进入设置后 t2也会进入同步代码块
synchronized (Singleton4.class) {
// 所以这里不再检验一遍就无法保证单例
if (INSTANCE != null) {
return INSTANCE;
}
// volatile保证了字节码执行的有序性(通过读屏障和写屏障)
// 可以避免出现先赋值 后执行构造方法的情况(此时会导致其他线程看到未构造完成的对象)
INSTANCE = new Singleton4();
return INSTANCE;
}
}
}
// 内部类懒加载
public final class Singleton5 {
private Singleton5() {}
private static Singleton5 INSTANCE;
public static Singleton5 getInstance() {
return LazyHolder.INSTANCE;
}
// 内部类在第一次被调用时加载
private static class LazyHolder {
static final Singleton5 INSTANCE = new Singleton5();
}
}
原文:https://www.cnblogs.com/jefferyyang/p/14427578.html