说句实在的单例模式是最为常见的java编程开发中的设计模式
绝大多数和我一样的小白大多可能对饿汉模式和懒汉模式比较了解了,精进的话需要了解和使用双重校验模式。
回顾一下:
/**
* 饿汉式
* 特点:直接在类加载的时候实例化对象
* 缺点: 违背了类加载的原则,造成类加载性能较低,没做到随用随加载
*/
public class HgSingleInstance {
private static HgSingleInstance mInstance = new HgSingleInstance();
private HgSingleInstance(){}
public static HgSingleInstance getInstance(){
return mInstance;
}
}
/**
* 懒汉式:
* 特点: 用的时候再加载
* 需要使用synchronized加锁的方式,不然会产生线程同步访问的问题
* 然而整个方法加锁会造成性能很低下的问题。
*/
public class LazySingleInstance {
private static LazySingleInstance mInstance;
private LazySingleInstance(){}
public static synchronized LazySingleInstance getInstance(){
if (mInstance == null){
mInstance = new LazySingleInstance();
}
return mInstance;
}
}
接下来看下我们的主角 DCL双重校验单例模式,规避了以上的问题
/**
* 双重校验: 不为空直接返回
* 当为空时即第一次初始化,只需在这时候进行加锁校验,只需并发一次同步即可
* 效率性能都较为优秀
*/
public class DCLSingle {
private static DCLSingle mInstance = null;
private DCLSingle(){}
public static DCLSingle getInstance(){
if (mInstance == null){
synchronized (DCLSingle.class){
if (mInstance == null){
mInstance = new DCLSingle();
}
}
}
return mInstance;
}
}
/**
* 双重校验: 不为空直接返回
* 当为空时即第一次初始化,只需在这时候进行加锁校验,只需并发一次同步即可
* 效率性能都较为优秀
* volatile解决指令集乱序问题
*/
public class DCLSingle {
private static volatile DCLSingle mInstance = null;
private DCLSingle(){}
public static DCLSingle getInstance(){
if (mInstance == null){
synchronized (DCLSingle.class){
if (mInstance == null){
mInstance = new DCLSingle();
}
}
}
return mInstance;
}
}
当然还有内部类和枚举单例的方式,后面再去进行学习。