目录
普通饿汉模式 – 线程安全
public class Out {
/**
* 加载类的时候就会执行(只执行一次)
* 会增加服务启动负担
*/
private static Out out = new Out();
public static Out getInstance() {
return out;
}
}
普通懒汉模式 – 非线程安全
public class Out {
private static Out out = null;
/**
* 该方法在并发时,会导致生成的对象被其他线程覆盖的问题
*/
public static Out getInstance() {
if (out == null) {
out = new Out();
}
return out;
}
}
加synchronized的懒汉模式 – 线程安全
public class Out {
private static Out out = null;
/**
* 方法加锁,线程安全
* 并发效率低
*/
public static synchronized Out getInstance() {
if (out == null) {
out = new Out();
}
return out;
}
}
双重校验锁 – 非线程安全
public static class Out {
private static Out out = null;
public static Out getInstance() {
/**
* 第一层判空会因为指令重排,导致判断实例不为空,从而返回一个没有初始化完成的实例给线程
*/
if (out == null) {
synchronized (Out.class) {
if (out == null) {
/**
* 指令重排机制会打乱下面的执行顺序
* memory = allocate(); //1.分配对象内存空间
* instance(memory); //2.初始化对象
* instance = memory; //3.设置instance指向刚分配的内存地址,此时instance!=null
*/
out = new Out();
}
}
}
return out;
}
}
加volatile的双重校验锁 – 线程安全
public static class Out {
private static volatile Out out = null;
public static Out getInstance() {
/**
* volatile禁止实例初始化过程的指令重排
*/
if (out == null) {
synchronized (Out.class) {
if (out == null) {
out = new Out();
}
}
}
return out;
}
}
静态内部类 – 线程安全(反序列化会生成新的实例)
public class Out {
/**
* 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
* 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载
*/
private static class Singleton{
/**
* 静态初始化器,由JVM来保证线程安全
*/
private static Out out = new Out();
}
public static Out getInstance(){
return Singleton.out;
}
}
枚举 – 线程安全(推荐写法)
public class Out {
/**
* 由JVM保证懒加载和线程安全(只有在调用的时候,才会生成单例,并且只会执行一次)
*
* 防止反序列化生成新对象(反射在通过newInstance创建对象时,会检查该类是否ENUM修饰,如果是则抛出异常,反射失败)
*/
public enum Singleton {
Singleton;
private static Out out = new Out();
}
public static Out getInstance() {
return Singleton.out;
}
}