单例类指仅仅被实例化一次的类。
实现线程安全的单例类有两种方式:
1. 双检锁+volatile关键字禁止重排序
public class DoubleCheckedLocking {
private volatile static Instance instance;
private DoubleCheckedLocking(){}
public static Instance getInstance() {
if (instance == null) { //第一次检查
synchronized (DoubleCheckedLocking.class) { //加锁
if (instance == null) //第二次检查
/*如果声明instances时不加volatile来禁止重排序
*编译器重排序后就会出现先将申请到的内存空间地址赋
*值给instance,
*后调用构造函数初始化内存空间的情况
*这时其他线程判断instance不为空,去访问时就会访问到
*一个未完成初始的实例
*/
instance = new Instance();
}
}
return instance;
}
}
2. 使用静态内部类保存实例
public class Singleton {
private Singleton(){}
private static class InstanceHolder {
public static Instance instance = new Instance();
}
public static Instance getInstance() {
//使用了类的静态成员,导致InstanceHolder类被初始化
//由于jvm类初始化时会自动加锁,所以利用jvm的特性实现了线程安全和延迟加载
return InstanceHolder.instance ;
}
}