标签:模式 实现 引用 方法 不为 volatil 时间 tin vat
目录
在特定场景下,我们需要在全局使用某一个对象的同一个实例,我们就需要保证一个对象不能存在多个实例。单例模式是一种很常见的设计模式;比如Servlet在Tomcat中是单例的,Spring IOC容器管理的Bean默认是单例的;单例模式就是为了保证一个对象对外只提供一个实例;单例模式实现方式比较多。
存在以下几种破坏单例的情况:
1.关键字new通过构造方法 2.多线程环境 3.反序列化 4.复制(clone) 5.反射
在实际应用中,实现单例模式时通常只需要考虑 1和2 两种情况;
根据实例化的时间不同可分为两大类:
一是饿汉模式,这种方式在类加载阶段完成实例化;
二是懒汉模式,这种方式在使用的时候才去实例化。
/**
* 单例模式——懒汉
* 双重校验
*/
class Singleton01 {
/**
* 使用volatile修饰的原因(禁止指令重排)
* 指令重排有可能导致先将未初始化的对象的引用赋值给instance变量,再进行初始化
* 也就是说可能出现一个线程还未对对象进行初始化,另外一个线程由于判断instance不为空于是获得了一个未初始化的对象
*/
private static volatile Singleton01 instance = null;
/**
* 私有化构造函数
*/
private Singleton01(){
System.out.println("我被实例化了");
}
public static Singleton01 getInstance(){
//如果还未实例化,则进行同步(因为实际上实例化成功之后就不需要进行同步操作了)
if(null == instance){
synchronized(Singleton01.class){
//最外层的判断没有进行同步,是非线程安全的,这里再次进行判断
if(null == instance){
instance = new Singleton01();
}
}
}
return instance;
}
}
/**
* 单例模式-饿汉
*
*/
class Singleton02 {
/**
* 在类加载初始化阶段实例化
* 在这个阶段由于虚拟机已经进行了同步,因此是线程安全的
*/
private static Singleton02 instance = new Singleton02();
/**
* 私有化构造函数
*/
private Singleton02(){
System.out.println("我被实例化了");
}
public static Singleton02 getInstance(){
return instance;
}
标签:模式 实现 引用 方法 不为 volatil 时间 tin vat
原文地址:https://www.cnblogs.com/fengwbetter/p/9393481.html