单例模式
什么是单例模式?
- 1、单例类只能有一个实例。
- 2、单例类必须自己创建自己的唯一实例。
- 3、单例类必须给所有其他对象提供这一实例。
应用:数据库的连接类,这样就可以确保只创建一次。节省资源。
单例模式代码:涉及懒加载、双重检查锁、volatile防止指令重排。
懒加载:在调用方法的时候才初始化对象。对应的是饿汉模式:private static Singleton singleton=new Singleton();
双检锁: 第一个是指synchronized(Singleton.class){…} 之所以将锁加在这里而不是方法上是因为加在方法上的话,多个线程调用这个方法都要抢锁,而实际上我们只需要保证创建对象时线程安全即可。所以为了更细粒度的锁我们加在了判空前。
第二个是指锁内还写了一个判空条件。这是因为线程A和B都进入了第一个判空条件内,然后这时候A加了锁,开始创建创建对象。结束后B线程也会创建对象。所以就需要再加一个判空条件。
volatile: singleton=new Singleton();其实分为三步:1.给Singleton分配空间。2.初始化对象(调用Singleton的构造方法)3.将singleton这个引用指向刚分配的内存地址。
但如果指令重排按照1,3,2的顺序进行。如果2还没有执行完,这时再来一个线程B发现singleton不为空了,直接return singleton,而我们的构造方法还没执行呢!这时就会出错。
class SingletonLazy {
// 使用private防止其他类使用
// 使用双重检查锁 必须加上volatile 防止指令重排
private volatile static SingletonLazy singletonLazy;
// 私有化构造器
private SingletonLazy() {};
public static SingletonLazy getInstance() {
// 双重检查锁
if (singletonLazy == null) {
synchronized (SingletonLazy.class) {
//双重检查锁
if (singletonLazy == null) {
singletonLazy = new SingletonLazy();
}
}
}
return singletonLazy;
}
}