/**
* 懒汉式-单例模式
* 多线程模式慎用,单例模式会失效,为解决这一问题,可以在静态方法上加“synchronized”表明锁住该类本身,同一时间点只有一个线程可以访问该方法
* 该方法虽然可以解决单例失效的问题,但却非常的消耗资源
*/
public class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton(){
}
private synchronized static LazySingleton getInstance(){
if(instance==null){
instance = new LazySingleton();
}
return instance;
}
/**
* 与上述方法等效
* @return
*/
private static LazySingleton getNewInstance(){
synchronized(LazySingleton.class) {
if (instance == null) {
instance = new LazySingleton();
}
}
return instance;
}
}
进一步完善,解决资源占用过多的问题
/**
* 引入双重锁概念,完善懒汉式-单例模式
*/
public class LazyDoubleCheckSingleton {
private volatile static LazyDoubleCheckSingleton instance = null;
private LazyDoubleCheckSingleton(){
}
public static LazyDoubleCheckSingleton getInstance(){
if(instance==null){
synchronized (LazyDoubleCheckSingleton.class) {
if(instance==null) {
instance = new LazyDoubleCheckSingleton();
// 这种方式虽然极大地解决了资源占用多过的问题,但也是存在线程安全性问题
// new 一个对象实际执行了三步操作,如下
// 1、为对象分配内存地址
// 2、初始化对象
// 3、将instance指向 新分配的内存地址
// 正常情况下,执行顺序1->2->3 如此执行,但多线程会造成重排序现象1->3->2,如要禁止该现象发生,
// 只需要在instance变量声明上加入一个关键字“volatile”,
// 多线程下 系统会有共享内存,volatile会使所有线程都能看见该变量的最新状态,
// 在赋值的时候,会将当前行缓存数据写回到共享内存,这样其他线程缓存的数据就会失效,从而再次向共享内存获取该变量的最新数据
}
}
}
return instance;
}
}
第二种完善方式,静态内部类
/**
* 完善懒汉式-单例模式 第二种方式:静态内部类
* 由于静态内部类被调用时,系统会先获取类对象锁,这样一来,多线程之间就屏蔽了StaticInnerClassSingleton 类实例化的全过程,
* 重排序现象仅对当前线程可见且有效
*/
public class StaticInnerClassSingleton {
private StaticInnerClassSingleton(){
}
private static class InnerClass{
private static StaticInnerClassSingleton instance = new StaticInnerClassSingleton();
}
public static StaticInnerClassSingleton getInstance(){
return InnerClass.instance;
}
}
【切记】单例模式,一定要记得创建私有构造函数